summaryrefslogtreecommitdiff
path: root/fitz
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2013-06-19 15:29:44 +0200
committerTor Andersson <tor.andersson@artifex.com>2013-06-20 16:45:35 +0200
commit0a927854a10e1e6b9770a81e2e1d9f3093631757 (patch)
tree3d65d820d9fdba2d0d394d99c36290c851b78ca0 /fitz
parent1ae8f19179c5f0f8c6352b3c7855465325d5449a (diff)
downloadmupdf-0a927854a10e1e6b9770a81e2e1d9f3093631757.tar.xz
Rearrange source files.
Diffstat (limited to 'fitz')
-rw-r--r--fitz/base_context.c210
-rw-r--r--fitz/base_error.c155
-rw-r--r--fitz/base_geometry.c483
-rw-r--r--fitz/base_getopt.c66
-rw-r--r--fitz/base_hash.c357
-rw-r--r--fitz/base_memory.c402
-rw-r--r--fitz/base_string.c264
-rw-r--r--fitz/base_time.c144
-rw-r--r--fitz/base_trans.c165
-rw-r--r--fitz/base_xml.c460
-rw-r--r--fitz/crypt_aes.c569
-rw-r--r--fitz/crypt_arc4.c98
-rw-r--r--fitz/crypt_md5.c272
-rw-r--r--fitz/crypt_pkcs7.c400
-rw-r--r--fitz/crypt_sha2.c393
-rw-r--r--fitz/dev_bbox.c231
-rw-r--r--fitz/dev_list.c851
-rw-r--r--fitz/dev_null.c388
-rw-r--r--fitz/dev_svg.c619
-rw-r--r--fitz/dev_trace.c339
-rw-r--r--fitz/doc_document.c274
-rw-r--r--fitz/doc_link.c65
-rw-r--r--fitz/doc_outline.c62
-rw-r--r--fitz/filt_basic.c662
-rw-r--r--fitz/filt_dctd.c256
-rw-r--r--fitz/filt_faxd.c776
-rw-r--r--fitz/filt_flate.c117
-rw-r--r--fitz/filt_jbig2d.c108
-rw-r--r--fitz/filt_lzwd.c224
-rw-r--r--fitz/filt_predict.c256
-rw-r--r--fitz/image_jpeg.c111
-rw-r--r--fitz/image_jpx.c253
-rw-r--r--fitz/image_png.c599
-rw-r--r--fitz/image_tiff.c867
-rw-r--r--fitz/memento.c1535
-rw-r--r--fitz/res_bitmap.c123
-rw-r--r--fitz/res_colorspace.c1277
-rw-r--r--fitz/res_font.c1094
-rw-r--r--fitz/res_func.c48
-rw-r--r--fitz/res_halftone.c202
-rw-r--r--fitz/res_image.c493
-rw-r--r--fitz/res_path.c507
-rw-r--r--fitz/res_pcl.c856
-rw-r--r--fitz/res_pixmap.c1062
-rw-r--r--fitz/res_pwg.c318
-rw-r--r--fitz/res_shade.c1096
-rw-r--r--fitz/res_store.c638
-rw-r--r--fitz/res_text.c154
-rw-r--r--fitz/stm_buffer.c390
-rw-r--r--fitz/stm_comp_buf.c75
-rw-r--r--fitz/stm_open.c210
-rw-r--r--fitz/stm_output.c100
-rw-r--r--fitz/stm_read.c219
-rw-r--r--fitz/text_extract.c1027
-rw-r--r--fitz/text_output.c400
-rw-r--r--fitz/text_paragraph.c1500
-rw-r--r--fitz/text_search.c279
57 files changed, 0 insertions, 25099 deletions
diff --git a/fitz/base_context.c b/fitz/base_context.c
deleted file mode 100644
index c65377a8..00000000
--- a/fitz/base_context.c
+++ /dev/null
@@ -1,210 +0,0 @@
-#include "mupdf/fitz.h"
-
-struct fz_id_context_s
-{
- int refs;
- int id;
-};
-
-static void
-fz_drop_id_context(fz_context *ctx)
-{
- int refs;
- fz_id_context *id = ctx->id;
-
- if (id == NULL)
- return;
- fz_lock(ctx, FZ_LOCK_ALLOC);
- refs = --id->refs;
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- if (refs == 0)
- fz_free(ctx, id);
-}
-
-static void
-fz_new_id_context(fz_context *ctx)
-{
- ctx->id = fz_malloc_struct(ctx, fz_id_context);
- ctx->id->refs = 1;
- ctx->id->id = 0;
-}
-
-static fz_id_context *
-fz_keep_id_context(fz_context *ctx)
-{
- fz_id_context *id = ctx->id;
-
- if (id == NULL)
- return NULL;
- fz_lock(ctx, FZ_LOCK_ALLOC);
- ++id->refs;
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- return id;
-}
-
-void
-fz_free_context(fz_context *ctx)
-{
- if (!ctx)
- return;
-
- /* Other finalisation calls go here (in reverse order) */
- fz_drop_glyph_cache_context(ctx);
- fz_drop_store_context(ctx);
- fz_free_aa_context(ctx);
- fz_drop_colorspace_context(ctx);
- fz_drop_font_context(ctx);
- fz_drop_id_context(ctx);
-
- if (ctx->warn)
- {
- fz_flush_warnings(ctx);
- fz_free(ctx, ctx->warn);
- }
-
- if (ctx->error)
- {
- assert(ctx->error->top == -1);
- fz_free(ctx, ctx->error);
- }
-
- /* Free the context itself */
- ctx->alloc->free(ctx->alloc->user, ctx);
-}
-
-/* Allocate new context structure, and initialise allocator, and sections
- * that aren't shared between contexts.
- */
-static fz_context *
-new_context_phase1(fz_alloc_context *alloc, fz_locks_context *locks)
-{
- fz_context *ctx;
-
- ctx = alloc->malloc(alloc->user, sizeof(fz_context));
- if (!ctx)
- return NULL;
- memset(ctx, 0, sizeof *ctx);
- ctx->alloc = alloc;
- ctx->locks = locks;
-
- ctx->glyph_cache = NULL;
-
- ctx->error = fz_malloc_no_throw(ctx, sizeof(fz_error_context));
- if (!ctx->error)
- goto cleanup;
- ctx->error->top = -1;
- ctx->error->errcode = FZ_ERROR_NONE;
- ctx->error->message[0] = 0;
-
- ctx->warn = fz_malloc_no_throw(ctx, sizeof(fz_warn_context));
- if (!ctx->warn)
- goto cleanup;
- ctx->warn->message[0] = 0;
- ctx->warn->count = 0;
-
- /* New initialisation calls for context entries go here */
- fz_try(ctx)
- {
- fz_new_aa_context(ctx);
- }
- fz_catch(ctx)
- {
- goto cleanup;
- }
-
- return ctx;
-
-cleanup:
- fprintf(stderr, "cannot create context (phase 1)\n");
- fz_free_context(ctx);
- return NULL;
-}
-
-fz_context *
-fz_new_context(fz_alloc_context *alloc, fz_locks_context *locks, unsigned int max_store)
-{
- fz_context *ctx;
-
- if (!alloc)
- alloc = &fz_alloc_default;
-
- if (!locks)
- locks = &fz_locks_default;
-
- ctx = new_context_phase1(alloc, locks);
- if (!ctx)
- return NULL;
-
- /* Now initialise sections that are shared */
- fz_try(ctx)
- {
- fz_new_store_context(ctx, max_store);
- fz_new_glyph_cache_context(ctx);
- fz_new_colorspace_context(ctx);
- fz_new_font_context(ctx);
- fz_new_id_context(ctx);
- }
- fz_catch(ctx)
- {
- fprintf(stderr, "cannot create context (phase 2)\n");
- fz_free_context(ctx);
- return NULL;
- }
- return ctx;
-}
-
-fz_context *
-fz_clone_context(fz_context *ctx)
-{
- /* We cannot safely clone the context without having locking/
- * unlocking functions. */
- if (ctx == NULL || ctx->locks == &fz_locks_default)
- return NULL;
- return fz_clone_context_internal(ctx);
-}
-
-fz_context *
-fz_clone_context_internal(fz_context *ctx)
-{
- fz_context *new_ctx;
-
- if (ctx == NULL || ctx->alloc == NULL)
- return NULL;
-
- new_ctx = new_context_phase1(ctx->alloc, ctx->locks);
- if (!new_ctx)
- return NULL;
-
- /* Inherit AA defaults from old context. */
- fz_copy_aa_context(new_ctx, ctx);
-
- /* Keep thread lock checking happy by copying pointers first and locking under new context */
- new_ctx->store = ctx->store;
- new_ctx->store = fz_keep_store_context(new_ctx);
- new_ctx->glyph_cache = ctx->glyph_cache;
- new_ctx->glyph_cache = fz_keep_glyph_cache(new_ctx);
- new_ctx->colorspace = ctx->colorspace;
- new_ctx->colorspace = fz_keep_colorspace_context(new_ctx);
- new_ctx->font = ctx->font;
- new_ctx->font = fz_keep_font_context(new_ctx);
- new_ctx->id = ctx->id;
- new_ctx->id = fz_keep_id_context(new_ctx);
-
- return new_ctx;
-}
-
-int
-fz_gen_id(fz_context *ctx)
-{
- int id;
- fz_lock(ctx, FZ_LOCK_ALLOC);
- /* We'll never wrap around in normal use, but if we *do*, then avoid
- * 0. */
- do
- {
- id = ++ctx->id->id;
- }
- while (id == 0);
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- return id;
-}
diff --git a/fitz/base_error.c b/fitz/base_error.c
deleted file mode 100644
index 50b3c5aa..00000000
--- a/fitz/base_error.c
+++ /dev/null
@@ -1,155 +0,0 @@
-#include "mupdf/fitz.h"
-
-/* Warning context */
-
-void fz_var_imp(void *var)
-{
- UNUSED(var); /* Do nothing */
-}
-
-void fz_flush_warnings(fz_context *ctx)
-{
- if (ctx->warn->count > 1)
- {
- fprintf(stderr, "warning: ... repeated %d times ...\n", ctx->warn->count);
- LOGE("warning: ... repeated %d times ...\n", ctx->warn->count);
- }
- ctx->warn->message[0] = 0;
- ctx->warn->count = 0;
-}
-
-void fz_warn(fz_context *ctx, const char *fmt, ...)
-{
- va_list ap;
- char buf[sizeof ctx->warn->message];
-
- va_start(ap, fmt);
- vsnprintf(buf, sizeof buf, fmt, ap);
- va_end(ap);
-
- if (!strcmp(buf, ctx->warn->message))
- {
- ctx->warn->count++;
- }
- else
- {
- fz_flush_warnings(ctx);
- fprintf(stderr, "warning: %s\n", buf);
- LOGE("warning: %s\n", buf);
- fz_strlcpy(ctx->warn->message, buf, sizeof ctx->warn->message);
- ctx->warn->count = 1;
- }
-}
-
-/* Error context */
-
-/* When we first setjmp, code is set to 0. Whenever we throw, we add 2 to
- * this code. Whenever we enter the always block, we add 1.
- *
- * fz_push_try sets code to 0.
- * If (fz_throw called within fz_try)
- * fz_throw makes code = 2.
- * If (no always block present)
- * enter catch region with code = 2. OK.
- * else
- * fz_always entered as code < 3; Makes code = 3;
- * if (fz_throw called within fz_always)
- * fz_throw makes code = 5
- * fz_always is not reentered.
- * catch region entered with code = 5. OK.
- * else
- * catch region entered with code = 3. OK
- * else
- * if (no always block present)
- * catch region not entered as code = 0. OK.
- * else
- * fz_always entered as code < 3. makes code = 1
- * if (fz_throw called within fz_always)
- * fz_throw makes code = 3;
- * fz_always NOT entered as code >= 3
- * catch region entered with code = 3. OK.
- * else
- * catch region entered with code = 1.
- */
-
-static void throw(fz_error_context *ex) FZ_NORETURN;
-
-static void throw(fz_error_context *ex)
-{
- if (ex->top >= 0) {
- fz_longjmp(ex->stack[ex->top].buffer, ex->stack[ex->top].code + 2);
- } else {
- fprintf(stderr, "uncaught exception: %s\n", ex->message);
- LOGE("uncaught exception: %s\n", ex->message);
- exit(EXIT_FAILURE);
- }
-}
-
-int fz_push_try(fz_error_context *ex)
-{
- assert(ex);
- ex->top++;
- /* Normal case, get out of here quick */
- if (ex->top < nelem(ex->stack)-1)
- return 1; /* We exit here, and the setjmp sets the code to 0 */
- /* We reserve the top slot on the exception stack purely to cope with
- * the case when we overflow. If we DO hit this, then we 'throw'
- * immediately - returning 0 stops the setjmp happening and takes us
- * direct to the always/catch clauses. */
- assert(ex->top == nelem(ex->stack)-1);
- strcpy(ex->message, "exception stack overflow!");
- ex->stack[ex->top].code = 2;
- fprintf(stderr, "error: %s\n", ex->message);
- LOGE("error: %s\n", ex->message);
- return 0;
-}
-
-int fz_caught(fz_context *ctx)
-{
- assert(ctx && ctx->error && ctx->error->errcode >= FZ_ERROR_NONE);
- return ctx->error->errcode;
-}
-
-const char *fz_caught_message(fz_context *ctx)
-{
- assert(ctx && ctx->error && ctx->error->errcode >= FZ_ERROR_NONE);
- return ctx->error->message;
-}
-
-void fz_throw(fz_context *ctx, int code, const char *fmt, ...)
-{
- va_list args;
- ctx->error->errcode = code;
- va_start(args, fmt);
- vsnprintf(ctx->error->message, sizeof ctx->error->message, fmt, args);
- va_end(args);
-
- fz_flush_warnings(ctx);
- fprintf(stderr, "error: %s\n", ctx->error->message);
- LOGE("error: %s\n", ctx->error->message);
-
- throw(ctx->error);
-}
-
-void fz_rethrow(fz_context *ctx)
-{
- assert(ctx && ctx->error && ctx->error->errcode >= FZ_ERROR_NONE);
- throw(ctx->error);
-}
-
-void fz_rethrow_message(fz_context *ctx, const char *fmt, ...)
-{
- va_list args;
-
- assert(ctx && ctx->error && ctx->error->errcode >= FZ_ERROR_NONE);
-
- va_start(args, fmt);
- vsnprintf(ctx->error->message, sizeof ctx->error->message, fmt, args);
- va_end(args);
-
- fz_flush_warnings(ctx);
- fprintf(stderr, "error: %s\n", ctx->error->message);
- LOGE("error: %s\n", ctx->error->message);
-
- throw(ctx->error);
-}
diff --git a/fitz/base_geometry.c b/fitz/base_geometry.c
deleted file mode 100644
index 81450246..00000000
--- a/fitz/base_geometry.c
+++ /dev/null
@@ -1,483 +0,0 @@
-#include "mupdf/fitz.h"
-
-#define MAX4(a,b,c,d) fz_max(fz_max(a,b), fz_max(c,d))
-#define MIN4(a,b,c,d) fz_min(fz_min(a,b), fz_min(c,d))
-
-/* A useful macro to add with overflow detection and clamping.
-
- We want to do "b = a + x", but to allow for overflow. Consider the
- top bits, and the cases in which overflow occurs:
-
- overflow a x b ~a^x a^b (~a^x)&(a^b)
- no 0 0 0 1 0 0
- yes 0 0 1 1 1 1
- no 0 1 0 0 0 0
- no 0 1 1 0 1 0
- no 1 0 0 0 1 0
- no 1 0 1 0 0 0
- yes 1 1 0 1 1 1
- no 1 1 1 1 0 0
-*/
-#define ADD_WITH_SAT(b,a,x) \
- ((b) = (a) + (x), (b) = (((~(a)^(x))&((a)^(b))) < 0 ? ((x) < 0 ? INT_MIN : INT_MAX) : (b)))
-
-/* Matrices, points and affine transformations */
-
-const fz_matrix fz_identity = { 1, 0, 0, 1, 0, 0 };
-
-fz_matrix *
-fz_concat(fz_matrix *dst, const fz_matrix *one, const fz_matrix *two)
-{
- fz_matrix dst2;
- dst2.a = one->a * two->a + one->b * two->c;
- dst2.b = one->a * two->b + one->b * two->d;
- dst2.c = one->c * two->a + one->d * two->c;
- dst2.d = one->c * two->b + one->d * two->d;
- dst2.e = one->e * two->a + one->f * two->c + two->e;
- dst2.f = one->e * two->b + one->f * two->d + two->f;
- *dst = dst2;
- return dst;
-}
-
-fz_matrix *
-fz_scale(fz_matrix *m, float sx, float sy)
-{
- m->a = sx; m->b = 0;
- m->c = 0; m->d = sy;
- m->e = 0; m->f = 0;
- return m;
-}
-
-fz_matrix *
-fz_pre_scale(fz_matrix *mat, float sx, float sy)
-{
- mat->a *= sx;
- mat->b *= sx;
- mat->c *= sy;
- mat->d *= sy;
- return mat;
-}
-
-fz_matrix *
-fz_shear(fz_matrix *mat, float h, float v)
-{
- mat->a = 1; mat->b = v;
- mat->c = h; mat->d = 1;
- mat->e = 0; mat->f = 0;
- return mat;
-}
-
-fz_matrix *
-fz_pre_shear(fz_matrix *mat, float h, float v)
-{
- float a = mat->a;
- float b = mat->b;
- mat->a += v * mat->c;
- mat->b += v * mat->d;
- mat->c += h * a;
- mat->d += h * b;
- return mat;
-}
-
-fz_matrix *
-fz_rotate(fz_matrix *m, float theta)
-{
- float s;
- float c;
-
- while (theta < 0)
- theta += 360;
- while (theta >= 360)
- theta -= 360;
-
- if (fabsf(0 - theta) < FLT_EPSILON)
- {
- s = 0;
- c = 1;
- }
- else if (fabsf(90.0f - theta) < FLT_EPSILON)
- {
- s = 1;
- c = 0;
- }
- else if (fabsf(180.0f - theta) < FLT_EPSILON)
- {
- s = 0;
- c = -1;
- }
- else if (fabsf(270.0f - theta) < FLT_EPSILON)
- {
- s = -1;
- c = 0;
- }
- else
- {
- s = sinf(theta * (float)M_PI / 180);
- c = cosf(theta * (float)M_PI / 180);
- }
-
- m->a = c; m->b = s;
- m->c = -s; m->d = c;
- m->e = 0; m->f = 0;
- return m;
-}
-
-fz_matrix *
-fz_pre_rotate(fz_matrix *m, float theta)
-{
- while (theta < 0)
- theta += 360;
- while (theta >= 360)
- theta -= 360;
-
- if (fabsf(0 - theta) < FLT_EPSILON)
- {
- /* Nothing to do */
- }
- else if (fabsf(90.0f - theta) < FLT_EPSILON)
- {
- float a = m->a;
- float b = m->b;
- m->a = m->c;
- m->b = m->d;
- m->c = -a;
- m->d = -b;
- }
- else if (fabsf(180.0f - theta) < FLT_EPSILON)
- {
- m->a = -m->a;
- m->b = -m->b;
- m->c = -m->c;
- m->d = -m->d;
- }
- else if (fabsf(270.0f - theta) < FLT_EPSILON)
- {
- float a = m->a;
- float b = m->b;
- m->a = -m->c;
- m->b = -m->d;
- m->c = a;
- m->d = b;
- }
- else
- {
- float s = sinf(theta * (float)M_PI / 180);
- float c = cosf(theta * (float)M_PI / 180);
- float a = m->a;
- float b = m->b;
- m->a = c * a + s * m->c;
- m->b = c * b + s * m->d;
- m->c =-s * a + c * m->c;
- m->d =-s * b + c * m->d;
- }
-
- return m;
-}
-
-fz_matrix *
-fz_translate(fz_matrix *m, float tx, float ty)
-{
- m->a = 1; m->b = 0;
- m->c = 0; m->d = 1;
- m->e = tx; m->f = ty;
- return m;
-}
-
-fz_matrix *
-fz_pre_translate(fz_matrix *mat, float tx, float ty)
-{
- mat->e += tx * mat->a + ty * mat->c;
- mat->f += tx * mat->b + ty * mat->d;
- return mat;
-}
-
-fz_matrix *
-fz_invert_matrix(fz_matrix *dst, const fz_matrix *src)
-{
- /* Be careful to cope with dst == src */
- float a = src->a;
- float det = a * src->d - src->b * src->c;
- if (det < -FLT_EPSILON || det > FLT_EPSILON)
- {
- float rdet = 1 / det;
- dst->a = src->d * rdet;
- dst->b = -src->b * rdet;
- dst->c = -src->c * rdet;
- dst->d = a * rdet;
- a = -src->e * dst->a - src->f * dst->c;
- dst->f = -src->e * dst->b - src->f * dst->d;
- dst->e = a;
- }
- else
- *dst = *src;
- return dst;
-}
-
-int
-fz_is_rectilinear(const fz_matrix *m)
-{
- return (fabsf(m->b) < FLT_EPSILON && fabsf(m->c) < FLT_EPSILON) ||
- (fabsf(m->a) < FLT_EPSILON && fabsf(m->d) < FLT_EPSILON);
-}
-
-float
-fz_matrix_expansion(const fz_matrix *m)
-{
- return sqrtf(fabsf(m->a * m->d - m->b * m->c));
-}
-
-float
-fz_matrix_max_expansion(const fz_matrix *m)
-{
- float max = fabsf(m->a);
- float x = fabsf(m->b);
- if (max < x)
- max = x;
- x = fabsf(m->c);
- if (max < x)
- max = x;
- x = fabsf(m->d);
- if (max < x)
- max = x;
- return max;
-}
-
-fz_point *
-fz_transform_point(fz_point *restrict p, const fz_matrix *restrict m)
-{
- float x = p->x;
- p->x = x * m->a + p->y * m->c + m->e;
- p->y = x * m->b + p->y * m->d + m->f;
- return p;
-}
-
-fz_point *
-fz_transform_vector(fz_point *restrict p, const fz_matrix *restrict m)
-{
- float x = p->x;
- p->x = x * m->a + p->y * m->c;
- p->y = x * m->b + p->y * m->d;
- return p;
-}
-
-void
-fz_normalize_vector(fz_point *p)
-{
- float len = p->x * p->x + p->y * p->y;
- if (len != 0)
- {
- len = sqrtf(len);
- p->x /= len;
- p->y /= len;
- }
-}
-
-/* Rectangles and bounding boxes */
-
-/* biggest and smallest integers that a float can represent perfectly (i.e. 24 bits) */
-#define MAX_SAFE_INT 16777216
-#define MIN_SAFE_INT -16777216
-
-const fz_rect fz_infinite_rect = { 1, 1, -1, -1 };
-const fz_rect fz_empty_rect = { 0, 0, 0, 0 };
-const fz_rect fz_unit_rect = { 0, 0, 1, 1 };
-
-const fz_irect fz_infinite_irect = { 1, 1, -1, -1 };
-const fz_irect fz_empty_irect = { 0, 0, 0, 0 };
-const fz_irect fz_unit_bbox = { 0, 0, 1, 1 };
-
-fz_irect *
-fz_irect_from_rect(fz_irect *restrict b, const fz_rect *restrict r)
-{
- b->x0 = fz_clamp(floorf(r->x0), MIN_SAFE_INT, MAX_SAFE_INT);
- b->y0 = fz_clamp(floorf(r->y0), MIN_SAFE_INT, MAX_SAFE_INT);
- b->x1 = fz_clamp(ceilf(r->x1), MIN_SAFE_INT, MAX_SAFE_INT);
- b->y1 = fz_clamp(ceilf(r->y1), MIN_SAFE_INT, MAX_SAFE_INT);
- return b;
-}
-
-fz_rect *
-fz_rect_from_irect(fz_rect *restrict r, const fz_irect *restrict a)
-{
- r->x0 = a->x0;
- r->y0 = a->y0;
- r->x1 = a->x1;
- r->y1 = a->y1;
- return r;
-}
-
-fz_irect *
-fz_round_rect(fz_irect * restrict b, const fz_rect *restrict r)
-{
- int i;
-
- i = floorf(r->x0 + 0.001);
- b->x0 = fz_clamp(i, MIN_SAFE_INT, MAX_SAFE_INT);
- i = floorf(r->y0 + 0.001);
- b->y0 = fz_clamp(i, MIN_SAFE_INT, MAX_SAFE_INT);
- i = ceilf(r->x1 - 0.001);
- b->x1 = fz_clamp(i, MIN_SAFE_INT, MAX_SAFE_INT);
- i = ceilf(r->y1 - 0.001);
- b->y1 = fz_clamp(i, MIN_SAFE_INT, MAX_SAFE_INT);
-
- return b;
-}
-
-fz_rect *
-fz_intersect_rect(fz_rect *restrict a, const fz_rect *restrict b)
-{
- /* Check for empty box before infinite box */
- if (fz_is_empty_rect(a)) return a;
- if (fz_is_empty_rect(b)) {
- *a = fz_empty_rect;
- return a;
- }
- if (fz_is_infinite_rect(b)) return a;
- if (fz_is_infinite_rect(a)) {
- *a = *b;
- return a;
- }
- if (a->x0 < b->x0)
- a->x0 = b->x0;
- if (a->y0 < b->y0)
- a->y0 = b->y0;
- if (a->x1 > b->x1)
- a->x1 = b->x1;
- if (a->y1 > b->y1)
- a->y1 = b->y1;
- if (a->x1 < a->x0 || a->y1 < a->y0)
- *a = fz_empty_rect;
- return a;
-}
-
-fz_irect *
-fz_intersect_irect(fz_irect *restrict a, const fz_irect *restrict b)
-{
- /* Check for empty box before infinite box */
- if (fz_is_empty_irect(a)) return a;
- if (fz_is_empty_irect(b))
- {
- *a = fz_empty_irect;
- return a;
- }
- if (fz_is_infinite_irect(b)) return a;
- if (fz_is_infinite_irect(a))
- {
- *a = *b;
- return a;
- }
- if (a->x0 < b->x0)
- a->x0 = b->x0;
- if (a->y0 < b->y0)
- a->y0 = b->y0;
- if (a->x1 > b->x1)
- a->x1 = b->x1;
- if (a->y1 > b->y1)
- a->y1 = b->y1;
- if (a->x1 < a->x0 || a->y1 < a->y0)
- *a = fz_empty_irect;
- return a;
-}
-
-fz_rect *
-fz_union_rect(fz_rect *restrict a, const fz_rect *restrict b)
-{
- /* Check for empty box before infinite box */
- if (fz_is_empty_rect(b)) return a;
- if (fz_is_empty_rect(a)) {
- *a = *b;
- return a;
- }
- if (fz_is_infinite_rect(a)) return a;
- if (fz_is_infinite_rect(b)) {
- *a = *b;
- return a;
- }
- if (a->x0 > b->x0)
- a->x0 = b->x0;
- if (a->y0 > b->y0)
- a->y0 = b->y0;
- if (a->x1 < b->x1)
- a->x1 = b->x1;
- if (a->y1 < b->y1)
- a->y1 = b->y1;
- return a;
-}
-
-fz_irect *
-fz_translate_irect(fz_irect *a, int xoff, int yoff)
-{
- int t;
-
- if (fz_is_empty_irect(a)) return a;
- if (fz_is_infinite_irect(a)) return a;
- a->x0 = ADD_WITH_SAT(t, a->x0, xoff);
- a->y0 = ADD_WITH_SAT(t, a->y0, yoff);
- a->x1 = ADD_WITH_SAT(t, a->x1, xoff);
- a->y1 = ADD_WITH_SAT(t, a->y1, yoff);
- return a;
-}
-
-fz_rect *
-fz_transform_rect(fz_rect *restrict r, const fz_matrix *restrict m)
-{
- fz_point s, t, u, v;
-
- if (fz_is_infinite_rect(r))
- return r;
-
- if (fabsf(m->b) < FLT_EPSILON && fabsf(m->c) < FLT_EPSILON)
- {
- if (m->a < 0)
- {
- float f = r->x0;
- r->x0 = r->x1;
- r->x1 = f;
- }
- if (m->d < 0)
- {
- float f = r->y0;
- r->y0 = r->y1;
- r->y1 = f;
- }
- fz_transform_point(fz_rect_min(r), m);
- fz_transform_point(fz_rect_max(r), m);
- return r;
- }
-
- s.x = r->x0; s.y = r->y0;
- t.x = r->x0; t.y = r->y1;
- u.x = r->x1; u.y = r->y1;
- v.x = r->x1; v.y = r->y0;
- fz_transform_point(&s, m);
- fz_transform_point(&t, m);
- fz_transform_point(&u, m);
- fz_transform_point(&v, m);
- r->x0 = MIN4(s.x, t.x, u.x, v.x);
- r->y0 = MIN4(s.y, t.y, u.y, v.y);
- r->x1 = MAX4(s.x, t.x, u.x, v.x);
- r->y1 = MAX4(s.y, t.y, u.y, v.y);
- return r;
-}
-
-fz_rect *
-fz_expand_rect(fz_rect *a, float expand)
-{
- if (fz_is_empty_rect(a)) return a;
- if (fz_is_infinite_rect(a)) return a;
- a->x0 -= expand;
- a->y0 -= expand;
- a->x1 += expand;
- a->y1 += expand;
- return a;
-}
-
-fz_rect *fz_include_point_in_rect(fz_rect *r, const fz_point *p)
-{
- if (p->x < r->x0) r->x0 = p->x;
- if (p->x > r->x1) r->x1 = p->x;
- if (p->y < r->y0) r->y0 = p->y;
- if (p->y > r->y1) r->y1 = p->y;
-
- return r;
-}
diff --git a/fitz/base_getopt.c b/fitz/base_getopt.c
deleted file mode 100644
index 2a6e5ac4..00000000
--- a/fitz/base_getopt.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * This is a version of the public domain getopt implementation by
- * Henry Spencer originally posted to net.sources.
- *
- * This file is in the public domain.
- */
-
-#include <stdio.h>
-#include <string.h>
-
-#define getopt fz_getopt
-#define optarg fz_optarg
-#define optind fz_optind
-
-char *optarg; /* Global argument pointer. */
-int optind = 0; /* Global argv index. */
-
-static char *scan = NULL; /* Private scan pointer. */
-
-int
-getopt(int argc, char *argv[], char *optstring)
-{
- char c;
- char *place;
-
- optarg = NULL;
-
- if (!scan || *scan == '\0') {
- if (optind == 0)
- optind++;
-
- if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
- return EOF;
- if (argv[optind][1] == '-' && argv[optind][2] == '\0') {
- optind++;
- return EOF;
- }
-
- scan = argv[optind]+1;
- optind++;
- }
-
- c = *scan++;
- place = strchr(optstring, c);
-
- if (!place || c == ':') {
- fprintf(stderr, "%s: unknown option -%c\n", argv[0], c);
- return '?';
- }
-
- place++;
- if (*place == ':') {
- if (*scan != '\0') {
- optarg = scan;
- scan = NULL;
- } else if( optind < argc ) {
- optarg = argv[optind];
- optind++;
- } else {
- fprintf(stderr, "%s: option requires argument -%c\n", argv[0], c);
- return ':';
- }
- }
-
- return c;
-}
diff --git a/fitz/base_hash.c b/fitz/base_hash.c
deleted file mode 100644
index 624cc305..00000000
--- a/fitz/base_hash.c
+++ /dev/null
@@ -1,357 +0,0 @@
-#include "mupdf/fitz.h"
-
-/*
-Simple hashtable with open addressing linear probe.
-Unlike text book examples, removing entries works
-correctly in this implementation, so it wont start
-exhibiting bad behaviour if entries are inserted
-and removed frequently.
-*/
-
-enum { MAX_KEY_LEN = 48 };
-typedef struct fz_hash_entry_s fz_hash_entry;
-
-struct fz_hash_entry_s
-{
- unsigned char key[MAX_KEY_LEN];
- void *val;
-};
-
-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;
-};
-
-static unsigned hash(unsigned char *s, int len)
-{
- unsigned val = 0;
- int i;
- for (i = 0; i < len; i++)
- {
- val += s[i];
- val += (val << 10);
- val ^= (val >> 6);
- }
- val += (val << 3);
- val ^= (val >> 11);
- val += (val << 15);
- return val;
-}
-
-fz_hash_table *
-fz_new_hash_table(fz_context *ctx, int initialsize, int keylen, int lock)
-{
- fz_hash_table *table;
-
- assert(keylen <= MAX_KEY_LEN);
-
- table = fz_malloc_struct(ctx, fz_hash_table);
- 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));
- memset(table->ents, 0, sizeof(fz_hash_entry) * table->size);
- }
- fz_catch(ctx)
- {
- fz_free(ctx, table);
- fz_rethrow(ctx);
- }
-
- return table;
-}
-
-void
-fz_empty_hash(fz_context *ctx, fz_hash_table *table)
-{
- table->load = 0;
- memset(table->ents, 0, sizeof(fz_hash_entry) * table->size);
-}
-
-int
-fz_hash_len(fz_context *ctx, fz_hash_table *table)
-{
- return table->size;
-}
-
-void *
-fz_hash_get_key(fz_context *ctx, fz_hash_table *table, int idx)
-{
- return table->ents[idx].key;
-}
-
-void *
-fz_hash_get_val(fz_context *ctx, fz_hash_table *table, int idx)
-{
- return table->ents[idx].val;
-}
-
-void
-fz_free_hash(fz_context *ctx, fz_hash_table *table)
-{
- fz_free(ctx, table->ents);
- fz_free(ctx, table);
-}
-
-static void *
-do_hash_insert(fz_context *ctx, fz_hash_table *table, void *key, void *val, unsigned *pos_ptr)
-{
- 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 ++;
- if (pos_ptr)
- *pos_ptr = pos;
- return NULL;
- }
-
- if (memcmp(key, ents[pos].key, table->keylen) == 0)
- {
- /* This is legal, but should happen rarely in the non
- * pos_ptr case. */
- if (pos_ptr)
- *pos_ptr = pos;
- else
- fz_warn(ctx, "assert: overwrite hash slot");
- return ents[pos].val;
- }
-
- pos = (pos + 1) % size;
- }
-}
-
-/* Entered with the lock taken, held throughout and at exit, UNLESS the lock
- * is the alloc lock in which case it may be momentarily dropped. */
-static void
-fz_resize_hash(fz_context *ctx, fz_hash_table *table, int newsize)
-{
- fz_hash_entry *oldents = table->ents;
- fz_hash_entry *newents;
- int oldsize = table->size;
- int oldload = table->load;
- int i;
-
- if (newsize < oldload * 8 / 10)
- {
- fz_warn(ctx, "assert: resize hash too small");
- return;
- }
-
- if (table->lock == FZ_LOCK_ALLOC)
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- newents = fz_malloc_array_no_throw(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! */
- if (table->lock == FZ_LOCK_ALLOC)
- fz_unlock(ctx, table->lock);
- fz_free(ctx, newents);
- if (table->lock == FZ_LOCK_ALLOC)
- fz_lock(ctx, table->lock);
- return;
- }
- }
- if (newents == NULL)
- fz_throw(ctx, FZ_ERROR_GENERIC, "hash table resize failed; out of memory (%d entries)", newsize);
- table->ents = newents;
- memset(table->ents, 0, sizeof(fz_hash_entry) * newsize);
- table->size = newsize;
- table->load = 0;
-
- for (i = 0; i < oldsize; i++)
- {
- if (oldents[i].val)
- {
- do_hash_insert(ctx, table, oldents[i].key, oldents[i].val, NULL);
- }
- }
-
- 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 *
-fz_hash_find(fz_context *ctx, fz_hash_table *table, void *key)
-{
- fz_hash_entry *ents = table->ents;
- 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)
- return NULL;
-
- if (memcmp(key, ents[pos].key, table->keylen) == 0)
- return ents[pos].val;
-
- pos = (pos + 1) % size;
- }
-}
-
-void *
-fz_hash_insert(fz_context *ctx, fz_hash_table *table, void *key, void *val)
-{
- if (table->load > table->size * 8 / 10)
- {
- fz_resize_hash(ctx, table, table->size * 2);
- }
-
- return do_hash_insert(ctx, table, key, val, NULL);
-}
-
-void *
-fz_hash_insert_with_pos(fz_context *ctx, fz_hash_table *table, void *key, void *val, unsigned *pos)
-{
- if (table->load > table->size * 8 / 10)
- {
- fz_resize_hash(ctx, table, table->size * 2);
- }
-
- return do_hash_insert(ctx, table, key, val, pos);
-}
-
-static void
-do_removal(fz_context *ctx, fz_hash_table *table, void *key, unsigned hole)
-{
- fz_hash_entry *ents = table->ents;
- unsigned size = table->size;
- unsigned look, code;
-
- if (table->lock >= 0)
- fz_assert_lock_held(ctx, table->lock);
-
- ents[hole].val = NULL;
-
- look = hole + 1;
- if (look == size)
- look = 0;
-
- while (ents[look].val)
- {
- code = hash(ents[look].key, table->keylen) % size;
- if ((code <= hole && hole < look) ||
- (look < code && code <= hole) ||
- (hole < look && look < code))
- {
- ents[hole] = ents[look];
- ents[look].val = NULL;
- hole = look;
- }
-
- look++;
- if (look == size)
- look = 0;
- }
-
- table->load --;
-}
-
-void
-fz_hash_remove(fz_context *ctx, fz_hash_table *table, void *key)
-{
- fz_hash_entry *ents = table->ents;
- 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)
- {
- fz_warn(ctx, "assert: remove non-existent hash entry");
- return;
- }
-
- if (memcmp(key, ents[pos].key, table->keylen) == 0)
- {
- do_removal(ctx, table, key, pos);
- return;
- }
-
- pos++;
- if (pos == size)
- pos = 0;
- }
-}
-
-void
-fz_hash_remove_fast(fz_context *ctx, fz_hash_table *table, void *key, unsigned pos)
-{
- fz_hash_entry *ents = table->ents;
-
- if (ents[pos].val == NULL || memcmp(key, ents[pos].key, table->keylen) != 0)
- {
- /* The value isn't there, or the key didn't match! The table
- * must have been rebuilt (or the contents moved) in the
- * meantime. Do the removal the slow way. */
- fz_hash_remove(ctx, table, key);
- }
- else
- do_removal(ctx, table, key, pos);
-}
-
-#ifndef NDEBUG
-void
-fz_print_hash(fz_context *ctx, FILE *out, fz_hash_table *table)
-{
- fz_print_hash_details(ctx, out, table, NULL);
-}
-
-void
-fz_print_hash_details(fz_context *ctx, FILE *out, fz_hash_table *table, void (*details)(FILE *,void*))
-{
- int i, k;
-
- fprintf(out, "cache load %d / %d\n", table->load, table->size);
-
- for (i = 0; i < table->size; i++)
- {
- if (!table->ents[i].val)
- fprintf(out, "table % 4d: empty\n", i);
- else
- {
- fprintf(out, "table % 4d: key=", i);
- for (k = 0; k < MAX_KEY_LEN; k++)
- fprintf(out, "%02x", ((char*)table->ents[i].key)[k]);
- if (details)
- details(out, table->ents[i].val);
- else
- fprintf(out, " val=$%p\n", table->ents[i].val);
- }
- }
-}
-#endif
diff --git a/fitz/base_memory.c b/fitz/base_memory.c
deleted file mode 100644
index f9e7b4f6..00000000
--- a/fitz/base_memory.c
+++ /dev/null
@@ -1,402 +0,0 @@
-#include "mupdf/fitz.h"
-
-/* Enable FITZ_DEBUG_LOCKING_TIMES below if you want to check the times
- * for which locks are held too. */
-#ifdef FITZ_DEBUG_LOCKING
-#undef FITZ_DEBUG_LOCKING_TIMES
-#endif
-
-static void *
-do_scavenging_malloc(fz_context *ctx, unsigned int size)
-{
- void *p;
- int phase = 0;
-
- fz_lock(ctx, FZ_LOCK_ALLOC);
- do {
- p = ctx->alloc->malloc(ctx->alloc->user, size);
- if (p != NULL)
- {
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- return p;
- }
- } while (fz_store_scavenge(ctx, size, &phase));
- fz_unlock(ctx, FZ_LOCK_ALLOC);
-
- return NULL;
-}
-
-static void *
-do_scavenging_realloc(fz_context *ctx, void *p, unsigned int size)
-{
- void *q;
- int phase = 0;
-
- fz_lock(ctx, FZ_LOCK_ALLOC);
- do {
- q = ctx->alloc->realloc(ctx->alloc->user, p, size);
- if (q != NULL)
- {
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- return q;
- }
- } while (fz_store_scavenge(ctx, size, &phase));
- fz_unlock(ctx, FZ_LOCK_ALLOC);
-
- return NULL;
-}
-
-void *
-fz_malloc(fz_context *ctx, unsigned int size)
-{
- void *p;
-
- if (size == 0)
- return NULL;
-
- p = do_scavenging_malloc(ctx, size);
- if (!p)
- fz_throw(ctx, FZ_ERROR_GENERIC, "malloc of %d bytes failed", size);
- return p;
-}
-
-void *
-fz_malloc_no_throw(fz_context *ctx, unsigned int size)
-{
- return do_scavenging_malloc(ctx, size);
-}
-
-void *
-fz_malloc_array(fz_context *ctx, unsigned int count, unsigned int size)
-{
- void *p;
-
- if (count == 0 || size == 0)
- return 0;
-
- if (count > UINT_MAX / size)
- fz_throw(ctx, FZ_ERROR_GENERIC, "malloc of array (%d x %d bytes) failed (integer overflow)", count, size);
-
- p = do_scavenging_malloc(ctx, count * size);
- if (!p)
- fz_throw(ctx, FZ_ERROR_GENERIC, "malloc of array (%d x %d bytes) failed", count, size);
- return p;
-}
-
-void *
-fz_malloc_array_no_throw(fz_context *ctx, unsigned int count, unsigned int size)
-{
- if (count == 0 || size == 0)
- return 0;
-
- if (count > UINT_MAX / size)
- {
- fprintf(stderr, "error: malloc of array (%d x %d bytes) failed (integer overflow)", count, size);
- return NULL;
- }
-
- return do_scavenging_malloc(ctx, count * size);
-}
-
-void *
-fz_calloc(fz_context *ctx, unsigned int count, unsigned int size)
-{
- void *p;
-
- if (count == 0 || size == 0)
- return 0;
-
- if (count > UINT_MAX / size)
- {
- fz_throw(ctx, FZ_ERROR_GENERIC, "calloc (%d x %d bytes) failed (integer overflow)", count, size);
- }
-
- p = do_scavenging_malloc(ctx, count * size);
- if (!p)
- {
- fz_throw(ctx, FZ_ERROR_GENERIC, "calloc (%d x %d bytes) failed", count, size);
- }
- memset(p, 0, count*size);
- return p;
-}
-
-void *
-fz_calloc_no_throw(fz_context *ctx, unsigned int count, unsigned int size)
-{
- void *p;
-
- if (count == 0 || size == 0)
- return 0;
-
- if (count > UINT_MAX / size)
- {
- fprintf(stderr, "error: calloc (%d x %d bytes) failed (integer overflow)\n", count, size);
- return NULL;
- }
-
- p = do_scavenging_malloc(ctx, count * size);
- if (p)
- {
- memset(p, 0, count*size);
- }
- return p;
-}
-
-void *
-fz_resize_array(fz_context *ctx, void *p, unsigned int count, unsigned int size)
-{
- void *np;
-
- if (count == 0 || size == 0)
- {
- fz_free(ctx, p);
- return 0;
- }
-
- if (count > UINT_MAX / size)
- fz_throw(ctx, FZ_ERROR_GENERIC, "resize array (%d x %d bytes) failed (integer overflow)", count, size);
-
- np = do_scavenging_realloc(ctx, p, count * size);
- if (!np)
- fz_throw(ctx, FZ_ERROR_GENERIC, "resize array (%d x %d bytes) failed", count, size);
- return np;
-}
-
-void *
-fz_resize_array_no_throw(fz_context *ctx, void *p, unsigned int count, unsigned int size)
-{
- if (count == 0 || size == 0)
- {
- fz_free(ctx, p);
- return 0;
- }
-
- if (count > UINT_MAX / size)
- {
- fprintf(stderr, "error: resize array (%d x %d bytes) failed (integer overflow)\n", count, size);
- return NULL;
- }
-
- return do_scavenging_realloc(ctx, p, count * size);
-}
-
-void
-fz_free(fz_context *ctx, void *p)
-{
- fz_lock(ctx, FZ_LOCK_ALLOC);
- ctx->alloc->free(ctx->alloc->user, p);
- fz_unlock(ctx, FZ_LOCK_ALLOC);
-}
-
-char *
-fz_strdup(fz_context *ctx, const char *s)
-{
- int len = strlen(s) + 1;
- char *ns = fz_malloc(ctx, len);
- memcpy(ns, s, len);
- return ns;
-}
-
-char *
-fz_strdup_no_throw(fz_context *ctx, const char *s)
-{
- int len = strlen(s) + 1;
- char *ns = fz_malloc_no_throw(ctx, len);
- if (ns)
- memcpy(ns, s, len);
- return ns;
-}
-
-static void *
-fz_malloc_default(void *opaque, unsigned int size)
-{
- return malloc(size);
-}
-
-static void *
-fz_realloc_default(void *opaque, void *old, unsigned int size)
-{
- return realloc(old, size);
-}
-
-static void
-fz_free_default(void *opaque, void *ptr)
-{
- free(ptr);
-}
-
-fz_alloc_context fz_alloc_default =
-{
- NULL,
- fz_malloc_default,
- fz_realloc_default,
- fz_free_default
-};
-
-static void
-fz_lock_default(void *user, int lock)
-{
-}
-
-static void
-fz_unlock_default(void *user, int lock)
-{
-}
-
-fz_locks_context fz_locks_default =
-{
- NULL,
- fz_lock_default,
- fz_unlock_default
-};
-
-#ifdef FITZ_DEBUG_LOCKING
-
-enum
-{
- FZ_LOCK_DEBUG_CONTEXT_MAX = 100
-};
-
-fz_context *fz_lock_debug_contexts[FZ_LOCK_DEBUG_CONTEXT_MAX];
-int fz_locks_debug[FZ_LOCK_DEBUG_CONTEXT_MAX][FZ_LOCK_MAX];
-#ifdef FITZ_DEBUG_LOCKING_TIMES
-int fz_debug_locking_inited = 0;
-int fz_lock_program_start;
-int fz_lock_time[FZ_LOCK_DEBUG_CONTEXT_MAX][FZ_LOCK_MAX] = { { 0 } };
-int fz_lock_taken[FZ_LOCK_DEBUG_CONTEXT_MAX][FZ_LOCK_MAX] = { { 0 } };
-
-/* We implement our own millisecond clock, as clock() cannot be trusted
- * when threads are involved. */
-static int ms_clock(void)
-{
-#ifdef _WIN32
- return (int)GetTickCount();
-#else
- struct timeval tp;
- gettimeofday(&tp, NULL);
- return (tp.tv_sec*1000) + (tp.tv_usec/1000);
-#endif
-}
-
-static void dump_lock_times(void)
-{
- int i, j;
- int prog_time = ms_clock() - fz_lock_program_start;
-
- for (j = 0; j < FZ_LOCK_MAX; j++)
- {
- int total = 0;
- for (i = 0; i < FZ_LOCK_DEBUG_CONTEXT_MAX; i++)
- {
- total += fz_lock_time[i][j];
- }
- printf("Lock %d held for %g seconds (%g%%)\n", j, ((double)total)/1000, 100.0*total/prog_time);
- }
- printf("Total program time %g seconds\n", ((double)prog_time)/1000);
-}
-
-#endif
-
-static int find_context(fz_context *ctx)
-{
- int i;
-
- for (i = 0; i < FZ_LOCK_DEBUG_CONTEXT_MAX; i++)
- {
- if (fz_lock_debug_contexts[i] == ctx)
- return i;
- if (fz_lock_debug_contexts[i] == NULL)
- {
- int gottit = 0;
- /* We've not locked on this context before, so use
- * this one for this new context. We might have other
- * threads trying here too though so, so claim it
- * atomically. No one has locked on this context
- * before, so we are safe to take the ALLOC lock. */
- ctx->locks->lock(ctx->locks->user, FZ_LOCK_ALLOC);
- /* If it's still free, then claim it as ours,
- * otherwise we'll keep hunting. */
- if (fz_lock_debug_contexts[i] == NULL)
- {
- gottit = 1;
- fz_lock_debug_contexts[i] = ctx;
-#ifdef FITZ_DEBUG_LOCKING_TIMES
- if (fz_debug_locking_inited == 0)
- {
- fz_debug_locking_inited = 1;
- fz_lock_program_start = ms_clock();
- atexit(dump_lock_times);
- }
-#endif
- }
- ctx->locks->unlock(ctx->locks->user, FZ_LOCK_ALLOC);
- if (gottit)
- return i;
- }
- }
- return -1;
-}
-
-void
-fz_assert_lock_held(fz_context *ctx, int lock)
-{
- int idx = find_context(ctx);
- if (idx < 0)
- return;
-
- if (fz_locks_debug[idx][lock] == 0)
- fprintf(stderr, "Lock %d not held when expected\n", lock);
-}
-
-void
-fz_assert_lock_not_held(fz_context *ctx, int lock)
-{
- int idx = find_context(ctx);
- if (idx < 0)
- return;
-
- if (fz_locks_debug[idx][lock] != 0)
- fprintf(stderr, "Lock %d held when not expected\n", lock);
-}
-
-void fz_lock_debug_lock(fz_context *ctx, int lock)
-{
- int i;
- int idx = find_context(ctx);
- if (idx < 0)
- return;
-
- if (fz_locks_debug[idx][lock] != 0)
- {
- fprintf(stderr, "Attempt to take lock %d when held already!\n", lock);
- }
- for (i = lock-1; i >= 0; i--)
- {
- if (fz_locks_debug[idx][i] != 0)
- {
- fprintf(stderr, "Lock ordering violation: Attempt to take lock %d when %d held already!\n", lock, i);
- }
- }
- fz_locks_debug[idx][lock] = 1;
-#ifdef FITZ_DEBUG_LOCKING_TIMES
- fz_lock_taken[idx][lock] = clock();
-#endif
-}
-
-void fz_lock_debug_unlock(fz_context *ctx, int lock)
-{
- int idx = find_context(ctx);
- if (idx < 0)
- return;
-
- if (fz_locks_debug[idx][lock] == 0)
- {
- fprintf(stderr, "Attempt to release lock %d when not held!\n", lock);
- }
- fz_locks_debug[idx][lock] = 0;
-#ifdef FITZ_DEBUG_LOCKING_TIMES
- fz_lock_time[idx][lock] += clock() - fz_lock_taken[idx][lock];
-#endif
-}
-
-#endif
diff --git a/fitz/base_string.c b/fitz/base_string.c
deleted file mode 100644
index b29cdbdc..00000000
--- a/fitz/base_string.c
+++ /dev/null
@@ -1,264 +0,0 @@
-#include "mupdf/fitz.h"
-
-char *
-fz_strsep(char **stringp, const char *delim)
-{
- char *ret = *stringp;
- if (!ret) return NULL;
- if ((*stringp = strpbrk(*stringp, delim)))
- *((*stringp)++) = '\0';
- return ret;
-}
-
-int
-fz_strlcpy(char *dst, const char *src, int siz)
-{
- register char *d = dst;
- register const char *s = src;
- register int n = siz;
-
- /* Copy as many bytes as will fit */
- if (n != 0 && --n != 0) {
- do {
- if ((*d++ = *s++) == 0)
- break;
- } while (--n != 0);
- }
-
- /* Not enough room in dst, add NUL and traverse rest of src */
- if (n == 0) {
- if (siz != 0)
- *d = '\0'; /* NUL-terminate dst */
- while (*s++)
- ;
- }
-
- return(s - src - 1); /* count does not include NUL */
-}
-
-int
-fz_strlcat(char *dst, const char *src, int siz)
-{
- register char *d = dst;
- register const char *s = src;
- register int n = siz;
- int dlen;
-
- /* Find the end of dst and adjust bytes left but don't go past end */
- while (*d != '\0' && n-- != 0)
- d++;
- dlen = d - dst;
- n = siz - dlen;
-
- if (n == 0)
- return dlen + strlen(s);
- while (*s != '\0') {
- if (n != 1) {
- *d++ = *s;
- n--;
- }
- s++;
- }
- *d = '\0';
-
- return dlen + (s - src); /* count does not include NUL */
-}
-
-enum
-{
- UTFmax = 4, /* maximum bytes per rune */
- Runesync = 0x80, /* cannot represent part of a UTF sequence (<) */
- Runeself = 0x80, /* rune and UTF sequences are the same (<) */
- Runeerror = 0xFFFD, /* decoding error in UTF */
- Runemax = 0x10FFFF, /* maximum rune value */
-};
-
-enum
-{
- Bit1 = 7,
- Bitx = 6,
- Bit2 = 5,
- Bit3 = 4,
- Bit4 = 3,
- Bit5 = 2,
-
- T1 = ((1<<(Bit1+1))-1) ^ 0xFF, /* 0000 0000 */
- Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */
- T2 = ((1<<(Bit2+1))-1) ^ 0xFF, /* 1100 0000 */
- T3 = ((1<<(Bit3+1))-1) ^ 0xFF, /* 1110 0000 */
- T4 = ((1<<(Bit4+1))-1) ^ 0xFF, /* 1111 0000 */
- T5 = ((1<<(Bit5+1))-1) ^ 0xFF, /* 1111 1000 */
-
- Rune1 = (1<<(Bit1+0*Bitx))-1, /* 0000 0000 0111 1111 */
- Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0111 1111 1111 */
- Rune3 = (1<<(Bit3+2*Bitx))-1, /* 1111 1111 1111 1111 */
- Rune4 = (1<<(Bit4+3*Bitx))-1, /* 0001 1111 1111 1111 1111 1111 */
-
- Maskx = (1<<Bitx)-1, /* 0011 1111 */
- Testx = Maskx ^ 0xFF, /* 1100 0000 */
-
- Bad = Runeerror,
-};
-
-int
-fz_chartorune(int *rune, const char *str)
-{
- int c, c1, c2, c3;
- long l;
-
- /*
- * one character sequence
- * 00000-0007F => T1
- */
- c = *(const unsigned char*)str;
- if(c < Tx) {
- *rune = c;
- return 1;
- }
-
- /*
- * two character sequence
- * 0080-07FF => T2 Tx
- */
- c1 = *(const unsigned char*)(str+1) ^ Tx;
- if(c1 & Testx)
- goto bad;
- if(c < T3) {
- if(c < T2)
- goto bad;
- l = ((c << Bitx) | c1) & Rune2;
- if(l <= Rune1)
- goto bad;
- *rune = l;
- return 2;
- }
-
- /*
- * three character sequence
- * 0800-FFFF => T3 Tx Tx
- */
- c2 = *(const unsigned char*)(str+2) ^ Tx;
- if(c2 & Testx)
- goto bad;
- if(c < T4) {
- l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;
- if(l <= Rune2)
- goto bad;
- *rune = l;
- return 3;
- }
-
- /*
- * four character sequence (21-bit value)
- * 10000-1FFFFF => T4 Tx Tx Tx
- */
- c3 = *(const unsigned char*)(str+3) ^ Tx;
- if (c3 & Testx)
- goto bad;
- if (c < T5) {
- l = ((((((c << Bitx) | c1) << Bitx) | c2) << Bitx) | c3) & Rune4;
- if (l <= Rune3)
- goto bad;
- *rune = l;
- return 4;
- }
- /*
- * Support for 5-byte or longer UTF-8 would go here, but
- * since we don't have that, we'll just fall through to bad.
- */
-
- /*
- * bad decoding
- */
-bad:
- *rune = Bad;
- return 1;
-}
-
-int
-fz_runetochar(char *str, int rune)
-{
- /* Runes are signed, so convert to unsigned for range check. */
- unsigned long c = (unsigned long)rune;
-
- /*
- * one character sequence
- * 00000-0007F => 00-7F
- */
- if(c <= Rune1) {
- str[0] = c;
- return 1;
- }
-
- /*
- * two character sequence
- * 0080-07FF => T2 Tx
- */
- if(c <= Rune2) {
- str[0] = T2 | (c >> 1*Bitx);
- str[1] = Tx | (c & Maskx);
- return 2;
- }
-
- /*
- * If the Rune is out of range, convert it to the error rune.
- * Do this test here because the error rune encodes to three bytes.
- * Doing it earlier would duplicate work, since an out of range
- * Rune wouldn't have fit in one or two bytes.
- */
- if (c > Runemax)
- c = Runeerror;
-
- /*
- * three character sequence
- * 0800-FFFF => T3 Tx Tx
- */
- if (c <= Rune3) {
- str[0] = T3 | (c >> 2*Bitx);
- str[1] = Tx | ((c >> 1*Bitx) & Maskx);
- str[2] = Tx | (c & Maskx);
- return 3;
- }
-
- /*
- * four character sequence (21-bit value)
- * 10000-1FFFFF => T4 Tx Tx Tx
- */
- str[0] = T4 | (c >> 3*Bitx);
- str[1] = Tx | ((c >> 2*Bitx) & Maskx);
- str[2] = Tx | ((c >> 1*Bitx) & Maskx);
- str[3] = Tx | (c & Maskx);
- return 4;
-}
-
-int
-fz_runelen(int c)
-{
- char str[10];
- return fz_runetochar(str, c);
-}
-
-float fz_atof(const char *s)
-{
- double d;
-
- /* The errno voodoo here checks for us reading numbers that are too
- * big to fit into a double. The checks for FLT_MAX ensure that we
- * don't read a number that's OK as a double and then become invalid
- * as we convert to a float. */
- errno = 0;
- d = strtod(s, NULL);
- if (errno == ERANGE || isnan(d)) {
- /* Return 1.0, as it's a small known value that won't cause a divide by 0. */
- return 1.0;
- }
- d = fz_clampd(d, -FLT_MAX, FLT_MAX);
- return (float)d;
-}
-
-int fz_atoi(const char *s)
-{
- if (s == NULL)
- return 0;
- return atoi(s);
-}
diff --git a/fitz/base_time.c b/fitz/base_time.c
deleted file mode 100644
index 0e3d21b5..00000000
--- a/fitz/base_time.c
+++ /dev/null
@@ -1,144 +0,0 @@
-#ifdef _MSC_VER
-
-#include "mupdf/fitz.h"
-
-#include <time.h>
-#include <windows.h>
-
-#ifndef _WINRT
-
-#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
-
-struct timeval;
-struct timezone;
-
-int gettimeofday(struct timeval *tv, struct timezone *tz)
-{
- FILETIME ft;
- unsigned __int64 tmpres = 0;
-
- if (tv)
- {
- GetSystemTimeAsFileTime(&ft);
-
- tmpres |= ft.dwHighDateTime;
- tmpres <<= 32;
- tmpres |= ft.dwLowDateTime;
-
- tmpres /= 10; /*convert into microseconds*/
- /*converting file time to unix epoch*/
- tmpres -= DELTA_EPOCH_IN_MICROSECS;
- tv->tv_sec = (long)(tmpres / 1000000UL);
- tv->tv_usec = (long)(tmpres % 1000000UL);
- }
-
- return 0;
-}
-
-#endif /* !_WINRT */
-
-char *
-fz_utf8_from_wchar(const wchar_t *s)
-{
- const wchar_t *src = s;
- char *d;
- char *dst;
- int len = 1;
-
- while (*src)
- {
- len += fz_runelen(*src++);
- }
-
- d = malloc(len);
- if (d != NULL)
- {
- dst = d;
- src = s;
- while (*src)
- {
- dst += fz_runetochar(dst, *src++);
- }
- *dst = 0;
- }
- return d;
-}
-
-wchar_t *
-fz_wchar_from_utf8(const char *s)
-{
- wchar_t *d, *r;
- int c;
- r = d = malloc((strlen(s) + 1) * sizeof(wchar_t));
- if (!r)
- return NULL;
- while (*s) {
- s += fz_chartorune(&c, s);
- *d++ = c;
- }
- *d = 0;
- return r;
-}
-
-FILE *
-fz_fopen_utf8(const char *name, const char *mode)
-{
- wchar_t *wname, *wmode;
- FILE *file;
-
- wname = fz_wchar_from_utf8(name);
- if (wname == NULL)
- {
- return NULL;
- }
-
- wmode = fz_wchar_from_utf8(mode);
- if (wmode == NULL)
- {
- free(wname);
- return NULL;
- }
-
- file = _wfopen(wname, wmode);
-
- free(wname);
- free(wmode);
- return file;
-}
-
-char **
-fz_argv_from_wargv(int argc, wchar_t **wargv)
-{
- char **argv;
- int i;
-
- argv = calloc(argc, sizeof(char *));
- if (argv == NULL)
- {
- fprintf(stderr, "Out of memory while processing command line args!\n");
- exit(1);
- }
-
- for (i = 0; i < argc; i++)
- {
- argv[i] = fz_utf8_from_wchar(wargv[i]);
- if (argv[i] == NULL)
- {
- fprintf(stderr, "Out of memory while processing command line args!\n");
- exit(1);
- }
- }
-
- return argv;
-}
-
-void
-fz_free_argv(int argc, char **argv)
-{
- int i;
- for (i = 0; i < argc; i++)
- free(argv[i]);
- free(argv);
-}
-
-#endif /* _MSC_VER */
diff --git a/fitz/base_trans.c b/fitz/base_trans.c
deleted file mode 100644
index 92582253..00000000
--- a/fitz/base_trans.c
+++ /dev/null
@@ -1,165 +0,0 @@
-#include "mupdf/fitz.h"
-
-static int
-fade(fz_pixmap *tpix, fz_pixmap *opix, fz_pixmap *npix, int time)
-{
- unsigned char *t, *o, *n;
- int size;
-
- if (!tpix || !opix || !npix || tpix->w != opix->w || opix->w != npix->w || tpix->h != opix->h || opix->h != npix->h || tpix->n != opix->n || opix->n != npix->n)
- return 0;
- size = tpix->w * tpix->h * tpix->n;
- t = tpix->samples;
- o = opix->samples;
- n = npix->samples;
- while (size-- > 0)
- {
- int op = *o++;
- int np = *n++;
- *t++ = ((op<<8) + ((np-op) * time) + 0x80)>>8;
- }
- return 1;
-}
-
-static int
-blind_horiz(fz_pixmap *tpix, fz_pixmap *opix, fz_pixmap *npix, int time)
-{
- unsigned char *t, *o, *n;
- int blind_height, span, position, y;
-
- if (!tpix || !opix || !npix || tpix->w != opix->w || opix->w != npix->w || tpix->h != opix->h || opix->h != npix->h || tpix->n != opix->n || opix->n != npix->n)
- return 0;
- span = tpix->w * tpix->n;
- blind_height = (tpix->h+7) / 8;
- position = blind_height * time / 256;
- t = tpix->samples;
- o = opix->samples;
- n = npix->samples;
- for (y = 0; y < tpix->h; y++)
- {
- memcpy(t, ((y % blind_height) <= position ? n : o), span);
- t += span;
- o += span;
- n += span;
- }
- return 1;
-}
-
-static int
-blind_vertical(fz_pixmap *tpix, fz_pixmap *opix, fz_pixmap *npix, int time)
-{
- unsigned char *t, *o, *n;
- int blind_width, span, position, y;
-
- if (!tpix || !opix || !npix || tpix->w != opix->w || opix->w != npix->w || tpix->h != opix->h || opix->h != npix->h || tpix->n != opix->n || opix->n != npix->n)
- return 0;
- span = tpix->w * tpix->n;
- blind_width = (tpix->w+7) / 8;
- position = blind_width * time / 256;
- blind_width *= tpix->n;
- position *= tpix->n;
- t = tpix->samples;
- o = opix->samples;
- n = npix->samples;
- for (y = 0; y < tpix->h; y++)
- {
- int w, x;
- x = 0;
- while ((w = span - x) > 0)
- {
- int p;
- if (w > blind_width)
- w = blind_width;
- p = position;
- if (p > w)
- p = w;
- memcpy(t, n, p);
- memcpy(t+position, o+position, w - p);
- x += blind_width;
- t += w;
- o += w;
- n += w;
- }
- }
- return 1;
-}
-
-static int
-wipe_tb(fz_pixmap *tpix, fz_pixmap *opix, fz_pixmap *npix, int time)
-{
- unsigned char *t, *o, *n;
- int span, position, y;
-
- if (!tpix || !opix || !npix || tpix->w != opix->w || opix->w != npix->w || tpix->h != opix->h || opix->h != npix->h || tpix->n != opix->n || opix->n != npix->n)
- return 0;
- span = tpix->w * tpix->n;
- position = tpix->h * time / 256;
- t = tpix->samples;
- o = opix->samples;
- n = npix->samples;
- for (y = 0; y < position; y++)
- {
- memcpy(t, n, span);
- t += span;
- o += span;
- n += span;
- }
- for (; y < tpix->h; y++)
- {
- memcpy(t, o, span);
- t += span;
- o += span;
- n += span;
- }
- return 1;
-}
-
-static int
-wipe_lr(fz_pixmap *tpix, fz_pixmap *opix, fz_pixmap *npix, int time)
-{
- unsigned char *t, *o, *n;
- int span, position, y;
-
- if (!tpix || !opix || !npix || tpix->w != opix->w || opix->w != npix->w || tpix->h != opix->h || opix->h != npix->h || tpix->n != opix->n || opix->n != npix->n)
- return 0;
- span = tpix->w * tpix->n;
- position = tpix->w * time / 256;
- position *= tpix->n;
- t = tpix->samples;
- o = opix->samples + position;
- n = npix->samples;
- for (y = 0; y < tpix->h; y++)
- {
- memcpy(t, n, position);
- memcpy(t+position, o, span-position);
- t += span;
- o += span;
- n += span;
- }
- return 1;
-}
-
-int fz_generate_transition(fz_pixmap *tpix, fz_pixmap *opix, fz_pixmap *npix, int time, fz_transition *trans)
-{
- switch (trans->type)
- {
- default:
- case FZ_TRANSITION_FADE:
- return fade(tpix, opix, npix, time);
- case FZ_TRANSITION_BLINDS:
- if (trans->vertical)
- return blind_vertical(tpix, opix, npix, time);
- else
- return blind_horiz(tpix, opix, npix, time);
- case FZ_TRANSITION_WIPE:
- switch (((trans->direction + 45 + 360) % 360) / 90)
- {
- default:
- case 0: return wipe_lr(tpix, opix, npix, time);
- case 1: return wipe_tb(tpix, npix, opix, 256-time);
- case 2: return wipe_lr(tpix, npix, opix, 256-time);
- case 3: return wipe_tb(tpix, opix, npix, time);
- }
- }
- return 0;
-}
diff --git a/fitz/base_xml.c b/fitz/base_xml.c
deleted file mode 100644
index 8c97562c..00000000
--- a/fitz/base_xml.c
+++ /dev/null
@@ -1,460 +0,0 @@
-#include "mupdf/fitz.h"
-
-struct parser
-{
- fz_xml *head;
- fz_context *ctx;
-};
-
-struct attribute
-{
- char name[40];
- char *value;
- struct attribute *next;
-};
-
-struct fz_xml_s
-{
- char name[40];
- char *text;
- struct attribute *atts;
- fz_xml *up, *down, *next;
-};
-
-static inline void indent(int n)
-{
- while (n--) putchar(' ');
-}
-
-void fz_debug_xml(fz_xml *item, int level)
-{
- while (item) {
- if (item->text) {
- printf("%s\n", item->text);
- } else {
- struct attribute *att;
- indent(level);
- printf("<%s", item->name);
- for (att = item->atts; att; att = att->next)
- printf(" %s=\"%s\"", att->name, att->value);
- if (item->down) {
- printf(">\n");
- fz_debug_xml(item->down, level + 1);
- indent(level);
- printf("</%s>\n", item->name);
- }
- else {
- printf("/>\n");
- }
- }
- item = item->next;
- }
-}
-
-fz_xml *fz_xml_next(fz_xml *item)
-{
- return item->next;
-}
-
-fz_xml *fz_xml_down(fz_xml *item)
-{
- return item->down;
-}
-
-char *fz_xml_text(fz_xml *item)
-{
- return item->text;
-}
-
-char *fz_xml_tag(fz_xml *item)
-{
- return item->name;
-}
-
-char *fz_xml_att(fz_xml *item, const char *name)
-{
- struct attribute *att;
- for (att = item->atts; att; att = att->next)
- if (!strcmp(att->name, name))
- return att->value;
- return NULL;
-}
-
-static void xml_free_attribute(fz_context *ctx, struct attribute *att)
-{
- while (att) {
- struct attribute *next = att->next;
- if (att->value)
- fz_free(ctx, att->value);
- fz_free(ctx, att);
- att = next;
- }
-}
-
-void fz_free_xml(fz_context *ctx, fz_xml *item)
-{
- while (item)
- {
- fz_xml *next = item->next;
- if (item->text)
- fz_free(ctx, item->text);
- if (item->atts)
- xml_free_attribute(ctx, item->atts);
- if (item->down)
- fz_free_xml(ctx, item->down);
- fz_free(ctx, item);
- item = next;
- }
-}
-
-void fz_detach_xml(fz_xml *node)
-{
- if (node->up)
- node->up->down = NULL;
-}
-
-static int xml_parse_entity(int *c, char *a)
-{
- char *b;
- if (a[1] == '#') {
- if (a[2] == 'x')
- *c = strtol(a + 3, &b, 16);
- else
- *c = strtol(a + 2, &b, 10);
- if (*b == ';')
- return b - a + 1;
- }
- else if (a[1] == 'l' && a[2] == 't' && a[3] == ';') {
- *c = '<';
- return 4;
- }
- else if (a[1] == 'g' && a[2] == 't' && a[3] == ';') {
- *c = '>';
- return 4;
- }
- else if (a[1] == 'a' && a[2] == 'm' && a[3] == 'p' && a[4] == ';') {
- *c = '&';
- return 5;
- }
- else if (a[1] == 'a' && a[2] == 'p' && a[3] == 'o' && a[4] == 's' && a[5] == ';') {
- *c = '\'';
- return 6;
- }
- else if (a[1] == 'q' && a[2] == 'u' && a[3] == 'o' && a[4] == 't' && a[5] == ';') {
- *c = '"';
- return 6;
- }
- *c = *a++;
- return 1;
-}
-
-static inline int isname(int c)
-{
- return c == '.' || c == '-' || c == '_' || c == ':' ||
- (c >= '0' && c <= '9') ||
- (c >= 'A' && c <= 'Z') ||
- (c >= 'a' && c <= 'z');
-}
-
-static inline int iswhite(int c)
-{
- return c == ' ' || c == '\r' || c == '\n' || c == '\t';
-}
-
-static void xml_emit_open_tag(struct parser *parser, char *a, char *b)
-{
- fz_xml *head, *tail;
-
- head = fz_malloc_struct(parser->ctx, fz_xml);
- if (b - a > sizeof(head->name) - 1)
- b = a + sizeof(head->name) - 1;
- memcpy(head->name, a, b - a);
- head->name[b - a] = 0;
-
- head->atts = NULL;
- head->text = NULL;
- head->up = parser->head;
- head->down = NULL;
- head->next = NULL;
-
- if (!parser->head->down) {
- parser->head->down = head;
- }
- else {
- tail = parser->head->down;
- while (tail->next)
- tail = tail->next;
- tail->next = head;
- }
-
- parser->head = head;
-}
-
-static void xml_emit_att_name(struct parser *parser, char *a, char *b)
-{
- fz_xml *head = parser->head;
- struct attribute *att;
-
- att = fz_malloc_struct(parser->ctx, struct attribute);
- if (b - a > sizeof(att->name) - 1)
- b = a + sizeof(att->name) - 1;
- memcpy(att->name, a, b - a);
- att->name[b - a] = 0;
- att->value = NULL;
- att->next = head->atts;
- head->atts = att;
-}
-
-static void xml_emit_att_value(struct parser *parser, char *a, char *b)
-{
- fz_xml *head = parser->head;
- struct attribute *att = head->atts;
- char *s;
- int c;
-
- /* entities are all longer than UTFmax so runetochar is safe */
- s = att->value = fz_malloc(parser->ctx, b - a + 1);
- while (a < b) {
- if (*a == '&') {
- a += xml_parse_entity(&c, a);
- s += fz_runetochar(s, c);
- }
- else {
- *s++ = *a++;
- }
- }
- *s = 0;
-}
-
-static void xml_emit_close_tag(struct parser *parser)
-{
- if (parser->head->up)
- parser->head = parser->head->up;
-}
-
-static void xml_emit_text(struct parser *parser, char *a, char *b)
-{
- static char *empty = "";
- fz_xml *head;
- char *s;
- int c;
-
- /* Skip all-whitespace text nodes */
- for (s = a; s < b; s++)
- if (!iswhite(*s))
- break;
- if (s == b)
- return;
-
- xml_emit_open_tag(parser, empty, empty);
- head = parser->head;
-
- /* entities are all longer than UTFmax so runetochar is safe */
- s = head->text = fz_malloc(parser->ctx, b - a + 1);
- while (a < b) {
- if (*a == '&') {
- a += xml_parse_entity(&c, a);
- s += fz_runetochar(s, c);
- }
- else {
- *s++ = *a++;
- }
- }
- *s = 0;
-
- xml_emit_close_tag(parser);
-}
-
-static char *xml_parse_document_imp(struct parser *x, char *p)
-{
- char *mark;
- int quote;
-
-parse_text:
- mark = p;
- while (*p && *p != '<') ++p;
- xml_emit_text(x, mark, p);
- if (*p == '<') { ++p; goto parse_element; }
- return NULL;
-
-parse_element:
- if (*p == '/') { ++p; goto parse_closing_element; }
- if (*p == '!') { ++p; goto parse_comment; }
- if (*p == '?') { ++p; goto parse_processing_instruction; }
- while (iswhite(*p)) ++p;
- if (isname(*p))
- goto parse_element_name;
- return "syntax error in element";
-
-parse_comment:
- if (*p == '[') goto parse_cdata;
- if (*p++ != '-') return "syntax error in comment (<! not followed by --)";
- if (*p++ != '-') return "syntax error in comment (<!- not followed by -)";
- mark = p;
- while (*p) {
- if (p[0] == '-' && p[1] == '-' && p[2] == '>') {
- p += 3;
- goto parse_text;
- }
- ++p;
- }
- return "end of data in comment";
-
-parse_cdata:
- if (p[1] != 'C' || p[2] != 'D' || p[3] != 'A' || p[4] != 'T' || p[5] != 'A' || p[6] != '[')
- return "syntax error in CDATA section";
- p += 7;
- mark = p;
- while (*p) {
- if (p[0] == ']' && p[1] == ']' && p[2] == '>') {
- p += 3;
- goto parse_text;
- }
- ++p;
- }
- return "end of data in CDATA section";
-
-parse_processing_instruction:
- while (*p) {
- if (p[0] == '?' && p[1] == '>') {
- p += 2;
- goto parse_text;
- }
- ++p;
- }
- return "end of data in processing instruction";
-
-parse_closing_element:
- while (iswhite(*p)) ++p;
- mark = p;
- while (isname(*p)) ++p;
- while (iswhite(*p)) ++p;
- if (*p != '>')
- return "syntax error in closing element";
- xml_emit_close_tag(x);
- ++p;
- goto parse_text;
-
-parse_element_name:
- mark = p;
- while (isname(*p)) ++p;
- xml_emit_open_tag(x, mark, p);
- if (*p == '>') { ++p; goto parse_text; }
- if (p[0] == '/' && p[1] == '>') {
- xml_emit_close_tag(x);
- p += 2;
- goto parse_text;
- }
- if (iswhite(*p))
- goto parse_attributes;
- return "syntax error after element name";
-
-parse_attributes:
- while (iswhite(*p)) ++p;
- if (isname(*p))
- goto parse_attribute_name;
- if (*p == '>') { ++p; goto parse_text; }
- if (p[0] == '/' && p[1] == '>') {
- xml_emit_close_tag(x);
- p += 2;
- goto parse_text;
- }
- return "syntax error in attributes";
-
-parse_attribute_name:
- mark = p;
- while (isname(*p)) ++p;
- xml_emit_att_name(x, mark, p);
- while (iswhite(*p)) ++p;
- if (*p == '=') { ++p; goto parse_attribute_value; }
- return "syntax error after attribute name";
-
-parse_attribute_value:
- while (iswhite(*p)) ++p;
- quote = *p++;
- if (quote != '"' && quote != '\'')
- return "missing quote character";
- mark = p;
- while (*p && *p != quote) ++p;
- if (*p == quote) {
- xml_emit_att_value(x, mark, p++);
- goto parse_attributes;
- }
- return "end of data in attribute value";
-}
-
-static char *convert_to_utf8(fz_context *doc, unsigned char *s, int n, int *dofree)
-{
- unsigned char *e = s + n;
- char *dst, *d;
- int c;
-
- if (s[0] == 0xFE && s[1] == 0xFF) {
- s += 2;
- dst = d = fz_malloc(doc, n * 2);
- while (s + 1 < e) {
- c = s[0] << 8 | s[1];
- d += fz_runetochar(d, c);
- s += 2;
- }
- *d = 0;
- *dofree = 1;
- return dst;
- }
-
- if (s[0] == 0xFF && s[1] == 0xFE) {
- s += 2;
- dst = d = fz_malloc(doc, n * 2);
- while (s + 1 < e) {
- c = s[0] | s[1] << 8;
- d += fz_runetochar(d, c);
- s += 2;
- }
- *d = 0;
- *dofree = 1;
- return dst;
- }
-
- *dofree = 0;
-
- if (s[0] == 0xEF && s[1] == 0xBB && s[2] == 0xBF)
- return (char*)s+3;
-
- return (char*)s;
-}
-
-fz_xml *
-fz_parse_xml(fz_context *ctx, unsigned char *s, int n)
-{
- struct parser parser;
- fz_xml root;
- char *p, *error;
- int dofree;
-
- /* s is already null-terminated (see xps_new_part) */
-
- memset(&root, 0, sizeof(root));
- parser.head = &root;
- parser.ctx = ctx;
-
- p = convert_to_utf8(ctx, s, n, &dofree);
-
- fz_try(ctx)
- {
- error = xml_parse_document_imp(&parser, p);
- if (error)
- fz_throw(ctx, FZ_ERROR_GENERIC, "%s", error);
- }
- fz_always(ctx)
- {
- if (dofree)
- fz_free(ctx, p);
- }
- fz_catch(ctx)
- {
- fz_free_xml(ctx, root.down);
- fz_rethrow(ctx);
- }
-
- return root.down;
-}
diff --git a/fitz/crypt_aes.c b/fitz/crypt_aes.c
deleted file mode 100644
index 6ce14903..00000000
--- a/fitz/crypt_aes.c
+++ /dev/null
@@ -1,569 +0,0 @@
-/*
- * FIPS-197 compliant AES implementation
- *
- * Copyright (C) 2006-2007 Christophe Devine
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code _must_ retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form may or may not reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- * * Neither the name of XySSL nor the names of its contributors may be
- * used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/*
- * The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
- *
- * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
- * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
- */
-
-#include "mupdf/fitz.h"
-
-#define aes_context fz_aes
-
-/* AES block cipher implementation from XYSSL */
-
-/*
- * 32-bit integer manipulation macros (little endian)
- */
-#ifndef GET_ULONG_LE
-#define GET_ULONG_LE(n,b,i) \
-{ \
- (n) = ( (unsigned long) (b)[(i)] ) \
- | ( (unsigned long) (b)[(i) + 1] << 8 ) \
- | ( (unsigned long) (b)[(i) + 2] << 16 ) \
- | ( (unsigned long) (b)[(i) + 3] << 24 ); \
-}
-#endif
-
-#ifndef PUT_ULONG_LE
-#define PUT_ULONG_LE(n,b,i) \
-{ \
- (b)[(i) ] = (unsigned char) ( (n) ); \
- (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
- (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
- (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
-}
-#endif
-
-/*
- * Forward S-box & tables
- */
-static unsigned char FSb[256];
-static unsigned long FT0[256];
-static unsigned long FT1[256];
-static unsigned long FT2[256];
-static unsigned long FT3[256];
-
-/*
- * Reverse S-box & tables
- */
-static unsigned char RSb[256];
-static unsigned long RT0[256];
-static unsigned long RT1[256];
-static unsigned long RT2[256];
-static unsigned long RT3[256];
-
-/*
- * Round constants
- */
-static unsigned long RCON[10];
-
-/*
- * Tables generation code
- */
-#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 )
-#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )
-#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 )
-
-static int aes_init_done = 0;
-
-static void aes_gen_tables( void )
-{
- int i, x, y, z;
- int pow[256];
- int log[256];
-
- /*
- * compute pow and log tables over GF(2^8)
- */
- for( i = 0, x = 1; i < 256; i++ )
- {
- pow[i] = x;
- log[x] = i;
- x = ( x ^ XTIME( x ) ) & 0xFF;
- }
-
- /*
- * calculate the round constants
- */
- for( i = 0, x = 1; i < 10; i++ )
- {
- RCON[i] = (unsigned long) x;
- x = XTIME( x ) & 0xFF;
- }
-
- /*
- * generate the forward and reverse S-boxes
- */
- FSb[0x00] = 0x63;
- RSb[0x63] = 0x00;
-
- for( i = 1; i < 256; i++ )
- {
- x = pow[255 - log[i]];
-
- y = x; y = ( (y << 1) | (y >> 7) ) & 0xFF;
- x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
- x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
- x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF;
- x ^= y ^ 0x63;
-
- FSb[i] = (unsigned char) x;
- RSb[x] = (unsigned char) i;
- }
-
- /*
- * generate the forward and reverse tables
- */
- for( i = 0; i < 256; i++ )
- {
- x = FSb[i];
- y = XTIME( x ) & 0xFF;
- z = ( y ^ x ) & 0xFF;
-
- FT0[i] = ( (unsigned long) y ) ^
- ( (unsigned long) x << 8 ) ^
- ( (unsigned long) x << 16 ) ^
- ( (unsigned long) z << 24 );
-
- FT1[i] = ROTL8( FT0[i] );
- FT2[i] = ROTL8( FT1[i] );
- FT3[i] = ROTL8( FT2[i] );
-
- x = RSb[i];
-
- RT0[i] = ( (unsigned long) MUL( 0x0E, x ) ) ^
- ( (unsigned long) MUL( 0x09, x ) << 8 ) ^
- ( (unsigned long) MUL( 0x0D, x ) << 16 ) ^
- ( (unsigned long) MUL( 0x0B, x ) << 24 );
-
- RT1[i] = ROTL8( RT0[i] );
- RT2[i] = ROTL8( RT1[i] );
- RT3[i] = ROTL8( RT2[i] );
- }
-}
-
-/*
- * AES key schedule (encryption)
- */
-int aes_setkey_enc( aes_context *ctx, const unsigned char *key, int keysize )
-{
- int i;
- unsigned long *RK;
-
-#if !defined(XYSSL_AES_ROM_TABLES)
- if( aes_init_done == 0 )
- {
- aes_gen_tables();
- aes_init_done = 1;
- }
-#endif
-
- switch( keysize )
- {
- case 128: ctx->nr = 10; break;
- case 192: ctx->nr = 12; break;
- case 256: ctx->nr = 14; break;
- default : return 1;
- }
-
-#if defined(PADLOCK_ALIGN16)
- ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf );
-#else
- ctx->rk = RK = ctx->buf;
-#endif
-
- for( i = 0; i < (keysize >> 5); i++ )
- {
- GET_ULONG_LE( RK[i], key, i << 2 );
- }
-
- switch( ctx->nr )
- {
- case 10:
-
- for( i = 0; i < 10; i++, RK += 4 )
- {
- RK[4] = RK[0] ^ RCON[i] ^
- ( FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^
- ( FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^
- ( FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^
- ( FSb[ ( RK[3] ) & 0xFF ] << 24 );
-
- RK[5] = RK[1] ^ RK[4];
- RK[6] = RK[2] ^ RK[5];
- RK[7] = RK[3] ^ RK[6];
- }
- break;
-
- case 12:
-
- for( i = 0; i < 8; i++, RK += 6 )
- {
- RK[6] = RK[0] ^ RCON[i] ^
- ( FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^
- ( FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^
- ( FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^
- ( FSb[ ( RK[5] ) & 0xFF ] << 24 );
-
- RK[7] = RK[1] ^ RK[6];
- RK[8] = RK[2] ^ RK[7];
- RK[9] = RK[3] ^ RK[8];
- RK[10] = RK[4] ^ RK[9];
- RK[11] = RK[5] ^ RK[10];
- }
- break;
-
- case 14:
-
- for( i = 0; i < 7; i++, RK += 8 )
- {
- RK[8] = RK[0] ^ RCON[i] ^
- ( FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^
- ( FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^
- ( FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^
- ( FSb[ ( RK[7] ) & 0xFF ] << 24 );
-
- RK[9] = RK[1] ^ RK[8];
- RK[10] = RK[2] ^ RK[9];
- RK[11] = RK[3] ^ RK[10];
-
- RK[12] = RK[4] ^
- ( FSb[ ( RK[11] ) & 0xFF ] ) ^
- ( FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^
- ( FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^
- ( FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );
-
- RK[13] = RK[5] ^ RK[12];
- RK[14] = RK[6] ^ RK[13];
- RK[15] = RK[7] ^ RK[14];
- }
- break;
-
- default:
-
- break;
- }
- return 0;
-}
-
-/*
- * AES key schedule (decryption)
- */
-int aes_setkey_dec(aes_context *ctx, const unsigned char *key, int keysize)
-{
- int i, j;
- aes_context cty;
- unsigned long *RK;
- unsigned long *SK;
-
- switch( keysize )
- {
- case 128: ctx->nr = 10; break;
- case 192: ctx->nr = 12; break;
- case 256: ctx->nr = 14; break;
- default: return 1;
- }
-
-#if defined(PADLOCK_ALIGN16)
- ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf );
-#else
- ctx->rk = RK = ctx->buf;
-#endif
-
- i = aes_setkey_enc( &cty, key, keysize );
- if (i)
- return i;
- SK = cty.rk + cty.nr * 4;
-
- *RK++ = *SK++;
- *RK++ = *SK++;
- *RK++ = *SK++;
- *RK++ = *SK++;
-
- for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 )
- {
- for( j = 0; j < 4; j++, SK++ )
- {
- *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^
- RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^
- RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^
- RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ];
- }
- }
-
- *RK++ = *SK++;
- *RK++ = *SK++;
- *RK++ = *SK++;
- *RK++ = *SK++;
-
- memset( &cty, 0, sizeof( aes_context ) );
- return 0;
-}
-
-#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
-{ \
- X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \
- FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
- FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
- FT3[ ( Y3 >> 24 ) & 0xFF ]; \
- \
- X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \
- FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
- FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
- FT3[ ( Y0 >> 24 ) & 0xFF ]; \
- \
- X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \
- FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
- FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
- FT3[ ( Y1 >> 24 ) & 0xFF ]; \
- \
- X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \
- FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
- FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
- FT3[ ( Y2 >> 24 ) & 0xFF ]; \
-}
-
-#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
-{ \
- X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \
- RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
- RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
- RT3[ ( Y1 >> 24 ) & 0xFF ]; \
- \
- X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \
- RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
- RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
- RT3[ ( Y2 >> 24 ) & 0xFF ]; \
- \
- X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \
- RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
- RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
- RT3[ ( Y3 >> 24 ) & 0xFF ]; \
- \
- X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \
- RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
- RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
- RT3[ ( Y0 >> 24 ) & 0xFF ]; \
-}
-
-/*
- * AES-ECB block encryption/decryption
- */
-void aes_crypt_ecb( aes_context *ctx,
- int mode,
- const unsigned char input[16],
- unsigned char output[16] )
-{
- int i;
- unsigned long *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
-
-#if defined(XYSSL_PADLOCK_C) && defined(XYSSL_HAVE_X86)
- if( padlock_supports( PADLOCK_ACE ) )
- {
- if( padlock_xcryptecb( ctx, mode, input, output ) == 0 )
- return;
- }
-#endif
-
- RK = ctx->rk;
-
- GET_ULONG_LE( X0, input, 0 ); X0 ^= *RK++;
- GET_ULONG_LE( X1, input, 4 ); X1 ^= *RK++;
- GET_ULONG_LE( X2, input, 8 ); X2 ^= *RK++;
- GET_ULONG_LE( X3, input, 12 ); X3 ^= *RK++;
-
- if( mode == AES_DECRYPT )
- {
- for( i = (ctx->nr >> 1) - 1; i > 0; i-- )
- {
- AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
- AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
- }
-
- AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
-
- X0 = *RK++ ^ ( RSb[ ( Y0 ) & 0xFF ] ) ^
- ( RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
- ( RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
- ( RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
-
- X1 = *RK++ ^ ( RSb[ ( Y1 ) & 0xFF ] ) ^
- ( RSb[ ( Y0 >>8 ) & 0xFF ] << 8 ) ^
- ( RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
- ( RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
-
- X2 = *RK++ ^ ( RSb[ ( Y2 ) & 0xFF ] ) ^
- ( RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
- ( RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
- ( RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
-
- X3 = *RK++ ^ ( RSb[ ( Y3 ) & 0xFF ] ) ^
- ( RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
- ( RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
- ( RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
- }
- else /* AES_ENCRYPT */
- {
- for( i = (ctx->nr >> 1) - 1; i > 0; i-- )
- {
- AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
- AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
- }
-
- AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
-
- X0 = *RK++ ^ ( FSb[ ( Y0 ) & 0xFF ] ) ^
- ( FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
- ( FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
- ( FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
-
- X1 = *RK++ ^ ( FSb[ ( Y1 ) & 0xFF ] ) ^
- ( FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
- ( FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
- ( FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
-
- X2 = *RK++ ^ ( FSb[ ( Y2 ) & 0xFF ] ) ^
- ( FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
- ( FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
- ( FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
-
- X3 = *RK++ ^ ( FSb[ ( Y3 ) & 0xFF ] ) ^
- ( FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
- ( FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
- ( FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
- }
-
- PUT_ULONG_LE( X0, output, 0 );
- PUT_ULONG_LE( X1, output, 4 );
- PUT_ULONG_LE( X2, output, 8 );
- PUT_ULONG_LE( X3, output, 12 );
-}
-
-/*
- * AES-CBC buffer encryption/decryption
- */
-void aes_crypt_cbc( aes_context *ctx,
- int mode,
- int length,
- unsigned char iv[16],
- const unsigned char *input,
- unsigned char *output )
-{
- int i;
- unsigned char temp[16];
-
-#if defined(XYSSL_PADLOCK_C) && defined(XYSSL_HAVE_X86)
- if( padlock_supports( PADLOCK_ACE ) )
- {
- if( padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 )
- return;
- }
-#endif
-
- if( mode == AES_DECRYPT )
- {
- while( length > 0 )
- {
- memcpy( temp, input, 16 );
- aes_crypt_ecb( ctx, mode, input, output );
-
- for( i = 0; i < 16; i++ )
- output[i] = (unsigned char)( output[i] ^ iv[i] );
-
- memcpy( iv, temp, 16 );
-
- input += 16;
- output += 16;
- length -= 16;
- }
- }
- else
- {
- while( length > 0 )
- {
- for( i = 0; i < 16; i++ )
- output[i] = (unsigned char)( input[i] ^ iv[i] );
-
- aes_crypt_ecb( ctx, mode, output, output );
- memcpy( iv, output, 16 );
-
- input += 16;
- output += 16;
- length -= 16;
- }
- }
-}
-
-/*
- * AES-CFB buffer encryption/decryption
- */
-void aes_crypt_cfb( aes_context *ctx,
- int mode,
- int length,
- int *iv_off,
- unsigned char iv[16],
- const unsigned char *input,
- unsigned char *output )
-{
- int c, n = *iv_off;
-
- if( mode == AES_DECRYPT )
- {
- while( length-- )
- {
- if( n == 0 )
- aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv );
-
- c = *input++;
- *output++ = (unsigned char)( c ^ iv[n] );
- iv[n] = (unsigned char) c;
-
- n = (n + 1) & 0x0F;
- }
- }
- else
- {
- while( length-- )
- {
- if( n == 0 )
- aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv );
-
- iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
-
- n = (n + 1) & 0x0F;
- }
- }
-
- *iv_off = n;
-}
diff --git a/fitz/crypt_arc4.c b/fitz/crypt_arc4.c
deleted file mode 100644
index 9c54fbae..00000000
--- a/fitz/crypt_arc4.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/* This code illustrates a sample implementation
- * of the Arcfour algorithm
- * Copyright (c) April 29, 1997 Kalle Kaukonen.
- * All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that this copyright
- * notice and disclaimer are retained.
- *
- * THIS SOFTWARE IS PROVIDED BY KALLE KAUKONEN AND CONTRIBUTORS ``AS
- * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KALLE
- * KAUKONEN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "mupdf/fitz.h"
-
-void
-fz_arc4_init(fz_arc4 *arc4, const unsigned char *key, unsigned keylen)
-{
- unsigned int t, u;
- unsigned int keyindex;
- unsigned int stateindex;
- unsigned char *state;
- unsigned int counter;
-
- state = arc4->state;
-
- arc4->x = 0;
- arc4->y = 0;
-
- for (counter = 0; counter < 256; counter++)
- {
- state[counter] = counter;
- }
-
- keyindex = 0;
- stateindex = 0;
-
- for (counter = 0; counter < 256; counter++)
- {
- t = state[counter];
- stateindex = (stateindex + key[keyindex] + t) & 0xff;
- u = state[stateindex];
-
- state[stateindex] = t;
- state[counter] = u;
-
- if (++keyindex >= keylen)
- {
- keyindex = 0;
- }
- }
-}
-
-static unsigned char
-fz_arc4_next(fz_arc4 *arc4)
-{
- unsigned int x;
- unsigned int y;
- unsigned int sx, sy;
- unsigned char *state;
-
- state = arc4->state;
-
- x = (arc4->x + 1) & 0xff;
- sx = state[x];
- y = (sx + arc4->y) & 0xff;
- sy = state[y];
-
- arc4->x = x;
- arc4->y = y;
-
- state[y] = sx;
- state[x] = sy;
-
- return state[(sx + sy) & 0xff];
-}
-
-void
-fz_arc4_encrypt(fz_arc4 *arc4, unsigned char *dest, const unsigned char *src, unsigned len)
-{
- unsigned int i;
- for (i = 0; i < len; i++)
- {
- unsigned char x;
- x = fz_arc4_next(arc4);
- dest[i] = src[i] ^ x;
- }
-}
diff --git a/fitz/crypt_md5.c b/fitz/crypt_md5.c
deleted file mode 100644
index 7490c0bc..00000000
--- a/fitz/crypt_md5.c
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
-MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
-
-Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991.
-All rights reserved.
-
-License to copy and use this software is granted provided that it
-is identified as the "RSA Data Security, Inc. MD5 Message-Digest
-Algorithm" in all material mentioning or referencing this software
-or this function.
-
-License is also granted to make and use derivative works provided
-that such works are identified as "derived from the RSA Data
-Security, Inc. MD5 Message-Digest Algorithm" in all material
-mentioning or referencing the derived work.
-
-RSA Data Security, Inc. makes no representations concerning either
-the merchantability of this software or the suitability of this
-software for any particular purpose. It is provided "as is"
-without express or implied warranty of any kind.
-
-These notices must be retained in any copies of any part of this
-documentation and/or software.
-*/
-
-#include "mupdf/fitz.h"
-
-/* Constants for MD5Transform routine */
-enum
-{
- S11 = 7, S12 = 12, S13 = 17, S14 = 22,
- S21 = 5, S22 = 9, S23 = 14, S24 = 20,
- S31 = 4, S32 = 11, S33 = 16, S34 = 23,
- S41 = 6, S42 = 10, S43 = 15, S44 = 21
-};
-
-static void encode(unsigned char *, const unsigned int *, const unsigned);
-static void decode(unsigned int *, const unsigned char *, const unsigned);
-static void transform(unsigned int state[4], const unsigned char block[64]);
-
-static unsigned char padding[64] =
-{
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/* F, G, H and I are basic MD5 functions */
-#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
-#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define I(x, y, z) ((y) ^ ((x) | (~z)))
-
-/* ROTATE rotates x left n bits */
-#define ROTATE(x, n) (((x) << (n)) | ((x) >> (32-(n))))
-
-/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
- * Rotation is separate from addition to prevent recomputation.
- */
-#define FF(a, b, c, d, x, s, ac) { \
- (a) += F ((b), (c), (d)) + (x) + (unsigned int)(ac); \
- (a) = ROTATE ((a), (s)); \
- (a) += (b); \
- }
-#define GG(a, b, c, d, x, s, ac) { \
- (a) += G ((b), (c), (d)) + (x) + (unsigned int)(ac); \
- (a) = ROTATE ((a), (s)); \
- (a) += (b); \
- }
-#define HH(a, b, c, d, x, s, ac) { \
- (a) += H ((b), (c), (d)) + (x) + (unsigned int)(ac); \
- (a) = ROTATE ((a), (s)); \
- (a) += (b); \
- }
-#define II(a, b, c, d, x, s, ac) { \
- (a) += I ((b), (c), (d)) + (x) + (unsigned int)(ac); \
- (a) = ROTATE ((a), (s)); \
- (a) += (b); \
- }
-
-static void encode(unsigned char *output, const unsigned int *input, const unsigned len)
-{
- unsigned i, j;
-
- for (i = 0, j = 0; j < len; i++, j += 4)
- {
- output[j] = (unsigned char)(input[i] & 0xff);
- output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
- output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
- output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
- }
-}
-
-static void decode(unsigned int *output, const unsigned char *input, const unsigned len)
-{
- unsigned i, j;
-
- for (i = 0, j = 0; j < len; i++, j += 4)
- {
- output[i] = ((unsigned int)input[j]) |
- (((unsigned int)input[j+1]) << 8) |
- (((unsigned int)input[j+2]) << 16) |
- (((unsigned int)input[j+3]) << 24);
- }
-}
-
-static void transform(unsigned int state[4], const unsigned char block[64])
-{
- unsigned int a = state[0];
- unsigned int b = state[1];
- unsigned int c = state[2];
- unsigned int d = state[3];
- unsigned int x[16];
-
- decode(x, block, 64);
-
- /* Round 1 */
- FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
- FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
- FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
- FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
- FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
- FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
- FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
- FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
- FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
- FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
- FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
- FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
- FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
- FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
- FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
- FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
-
- /* Round 2 */
- GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
- GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
- GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
- GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
- GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
- GG (d, a, b, c, x[10], S22, 0x02441453); /* 22 */
- GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
- GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
- GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
- GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
- GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
- GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
- GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
- GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
- GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
- GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
-
- /* Round 3 */
- HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
- HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
- HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
- HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
- HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
- HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
- HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
- HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
- HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
- HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
- HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
- HH (b, c, d, a, x[ 6], S34, 0x04881d05); /* 44 */
- HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
- HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
- HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
- HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
-
- /* Round 4 */
- II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
- II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
- II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
- II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
- II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
- II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
- II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
- II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
- II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
- II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
- II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
- II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
- II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
- II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
- II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
- II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
-
- state[0] += a;
- state[1] += b;
- state[2] += c;
- state[3] += d;
-
- /* Zeroize sensitive information */
- memset(x, 0, sizeof (x));
-}
-
-/* MD5 initialization. Begins an MD5 operation, writing a new context. */
-void fz_md5_init(fz_md5 *context)
-{
- context->count[0] = context->count[1] = 0;
-
- /* Load magic initialization constants */
- context->state[0] = 0x67452301;
- context->state[1] = 0xefcdab89;
- context->state[2] = 0x98badcfe;
- context->state[3] = 0x10325476;
-}
-
-/* MD5 block update operation. Continues an MD5 message-digest operation,
- * processing another message block, and updating the context.
- */
-void fz_md5_update(fz_md5 *context, const unsigned char *input, unsigned inlen)
-{
- unsigned i, index, partlen;
-
- /* Compute number of bytes mod 64 */
- index = (unsigned)((context->count[0] >> 3) & 0x3F);
-
- /* Update number of bits */
- context->count[0] += (unsigned int) inlen << 3;
- if (context->count[0] < (unsigned int) inlen << 3)
- context->count[1] ++;
- context->count[1] += (unsigned int) inlen >> 29;
-
- partlen = 64 - index;
-
- /* Transform as many times as possible. */
- if (inlen >= partlen)
- {
- memcpy(context->buffer + index, input, partlen);
- transform(context->state, context->buffer);
-
- for (i = partlen; i + 63 < inlen; i += 64)
- transform(context->state, input + i);
-
- index = 0;
- }
- else
- {
- i = 0;
- }
-
- /* Buffer remaining input */
- memcpy(context->buffer + index, input + i, inlen - i);
-}
-
-/* MD5 finalization. Ends an MD5 message-digest operation, writing the
- * the message digest and zeroizing the context.
- */
-void fz_md5_final(fz_md5 *context, unsigned char digest[16])
-{
- unsigned char bits[8];
- unsigned index, padlen;
-
- /* Save number of bits */
- encode(bits, context->count, 8);
-
- /* Pad out to 56 mod 64 */
- index = (unsigned)((context->count[0] >> 3) & 0x3f);
- padlen = index < 56 ? 56 - index : 120 - index;
- fz_md5_update(context, padding, padlen);
-
- /* Append length (before padding) */
- fz_md5_update(context, bits, 8);
-
- /* Store state in digest */
- encode(digest, context->state, 16);
-
- /* Zeroize sensitive information */
- memset(context, 0, sizeof(fz_md5));
-}
diff --git a/fitz/crypt_pkcs7.c b/fitz/crypt_pkcs7.c
deleted file mode 100644
index 1bc50b6e..00000000
--- a/fitz/crypt_pkcs7.c
+++ /dev/null
@@ -1,400 +0,0 @@
-#include "mupdf/pdf.h" // TODO: move this file to pdf module
-
-#ifdef HAVE_OPENSSL
-
-#include "openssl/err.h"
-#include "openssl/bio.h"
-#include "openssl/asn1.h"
-#include "openssl/x509.h"
-#include "openssl/err.h"
-#include "openssl/objects.h"
-#include "openssl/pem.h"
-#include "openssl/pkcs7.h"
-
-enum
-{
- SEG_START = 0,
- SEG_SIZE = 1
-};
-
-typedef struct bsegs_struct
-{
- int (*seg)[2];
- int nsegs;
- int current_seg;
- int seg_pos;
-} BIO_SEGS_CTX;
-
-static int bsegs_read(BIO *b, char *buf, int size)
-{
- BIO_SEGS_CTX *ctx = (BIO_SEGS_CTX *)b->ptr;
- int read = 0;
-
- while (size > 0 && ctx->current_seg < ctx->nsegs)
- {
- int nb = ctx->seg[ctx->current_seg][SEG_SIZE] - ctx->seg_pos;
-
- if (nb > size)
- nb = size;
-
- if (nb > 0)
- {
- if (ctx->seg_pos == 0)
- (void)BIO_seek(b->next_bio, ctx->seg[ctx->current_seg][SEG_START]);
-
- (void)BIO_read(b->next_bio, buf, nb);
- ctx->seg_pos += nb;
- read += nb;
- buf += nb;
- size -= nb;
- }
- else
- {
- ctx->current_seg++;
-
- if (ctx->current_seg < ctx->nsegs)
- ctx->seg_pos = 0;
- }
- }
-
- return read;
-}
-
-static long bsegs_ctrl(BIO *b, int cmd, long arg1, void *arg2)
-{
- return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
-}
-
-static int bsegs_new(BIO *b)
-{
- BIO_SEGS_CTX *ctx;
-
- ctx = (BIO_SEGS_CTX *)malloc(sizeof(BIO_SEGS_CTX));
- if (ctx == NULL)
- return 0;
-
- ctx->current_seg = 0;
- ctx->seg_pos = 0;
- ctx->seg = NULL;
- ctx->nsegs = 0;
-
- b->init = 1;
- b->ptr = (char *)ctx;
- b->flags = 0;
- b->num = 0;
-
- return 1;
-}
-
-static int bsegs_free(BIO *b)
-{
- if (b == NULL)
- return 0;
-
- free(b->ptr);
- b->ptr = NULL;
- b->init = 0;
- b->flags = 0;
-
- return 1;
-}
-
-static long bsegs_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
-{
- return BIO_callback_ctrl(b->next_bio, cmd, fp);
-}
-
-static BIO_METHOD methods_bsegs =
-{
- 0,"segment reader",
- NULL,
- bsegs_read,
- NULL,
- NULL,
- bsegs_ctrl,
- bsegs_new,
- bsegs_free,
- bsegs_callback_ctrl,
-};
-
-static BIO_METHOD *BIO_f_segments(void)
-{
- return &methods_bsegs;
-}
-
-static void BIO_set_segments(BIO *b, int (*seg)[2], int nsegs)
-{
- BIO_SEGS_CTX *ctx = (BIO_SEGS_CTX *)b->ptr;
-
- ctx->seg = seg;
- ctx->nsegs = nsegs;
-}
-
-typedef struct verify_context_s
-{
- X509_STORE_CTX x509_ctx;
- char certdesc[256];
- int err;
-} verify_context;
-
-static int verify_callback(int ok, X509_STORE_CTX *ctx)
-{
- verify_context *vctx;
- X509 *err_cert;
- int err, depth;
-
- vctx = (verify_context *)ctx;
-
- err_cert = X509_STORE_CTX_get_current_cert(ctx);
- err = X509_STORE_CTX_get_error(ctx);
- depth = X509_STORE_CTX_get_error_depth(ctx);
-
- X509_NAME_oneline(X509_get_subject_name(err_cert), vctx->certdesc, sizeof(vctx->certdesc));
-
- if (!ok && depth >= 6)
- {
- X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_CHAIN_TOO_LONG);
- }
-
- switch (ctx->error)
- {
- case X509_V_ERR_INVALID_PURPOSE:
- case X509_V_ERR_CERT_HAS_EXPIRED:
- case X509_V_ERR_KEYUSAGE_NO_CERTSIGN:
- err = X509_V_OK;
- X509_STORE_CTX_set_error(ctx, X509_V_OK);
- ok = 1;
- break;
-
- case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
- /*
- In this case, don't reset err to X509_V_OK, so that it can be reported,
- although we do return 1, so that the digest will still be checked
- */
- ok = 1;
- break;
-
- default:
- break;
- }
-
- if (ok && vctx->err == X509_V_OK)
- vctx->err = err;
- return ok;
-}
-
-static int pk7_verify(X509_STORE *cert_store, PKCS7 *p7, BIO *detached, char *ebuf, int ebufsize)
-{
- PKCS7_SIGNER_INFO *si;
- verify_context vctx;
- BIO *p7bio=NULL;
- char readbuf[1024*4];
- int res = 1;
- int i;
- STACK_OF(PKCS7_SIGNER_INFO) *sk;
-
- vctx.err = X509_V_OK;
- ebuf[0] = 0;
-
- OpenSSL_add_all_algorithms();
-
- EVP_add_digest(EVP_md5());
- EVP_add_digest(EVP_sha1());
-
- ERR_load_crypto_strings();
-
- ERR_clear_error();
-
- X509_VERIFY_PARAM_set_flags(cert_store->param, X509_V_FLAG_CB_ISSUER_CHECK);
- X509_STORE_set_verify_cb_func(cert_store, verify_callback);
-
- p7bio = PKCS7_dataInit(p7, detached);
-
- /* We now have to 'read' from p7bio to calculate digests etc. */
- while (BIO_read(p7bio, readbuf, sizeof(readbuf)) > 0)
- ;
-
- /* We can now verify signatures */
- sk = PKCS7_get_signer_info(p7);
- if (sk == NULL)
- {
- /* there are no signatures on this data */
- res = 0;
- strncpy(ebuf, "No signatures", sizeof(ebuf));
- goto exit;
- }
-
- for (i=0; i<sk_PKCS7_SIGNER_INFO_num(sk); i++)
- {
- int rc;
- si = sk_PKCS7_SIGNER_INFO_value(sk, i);
- rc = PKCS7_dataVerify(cert_store, &vctx.x509_ctx, p7bio,p7, si);
- if (rc <= 0 || vctx.err != X509_V_OK)
- {
- char tbuf[120];
-
- if (rc <= 0)
- {
- strncpy(ebuf, ERR_error_string(ERR_get_error(), tbuf), ebufsize-1);
- }
- else
- {
- /* Error while checking the certificate chain */
- snprintf(ebuf, ebufsize-1, "%s(%d): %s", X509_verify_cert_error_string(vctx.err), vctx.err, vctx.certdesc);
- }
-
- ebuf[ebufsize-1] = 0;
-
- res = 0;
- goto exit;
- }
- }
-
-exit:
- X509_STORE_CTX_cleanup(&vctx.x509_ctx);
- ERR_free_strings();
-
- return res;
-}
-
-static unsigned char adobe_ca[] =
-{
-#include "gen_adobe_ca.h"
-};
-
-static int verify_sig(char *sig, int sig_len, char *file, int (*byte_range)[2], int byte_range_len, char *ebuf, int ebufsize)
-{
- PKCS7 *pk7sig = NULL;
- PKCS7 *pk7cert = NULL;
- X509_STORE *st = NULL;
- BIO *bsig = NULL;
- BIO *bcert = NULL;
- BIO *bdata = NULL;
- BIO *bsegs = NULL;
- STACK_OF(X509) *certs = NULL;
- int t;
- int res = 0;
-
- bsig = BIO_new_mem_buf(sig, sig_len);
- pk7sig = d2i_PKCS7_bio(bsig, NULL);
- if (pk7sig == NULL)
- goto exit;
-
- bdata = BIO_new(BIO_s_file());
- BIO_read_filename(bdata, file);
-
- bsegs = BIO_new(BIO_f_segments());
- if (bsegs == NULL)
- goto exit;
-
- bsegs->next_bio = bdata;
- BIO_set_segments(bsegs, byte_range, byte_range_len);
-
- /* Find the certificates in the pk7 file */
- bcert = BIO_new_mem_buf(adobe_ca, sizeof(adobe_ca));
- pk7cert = d2i_PKCS7_bio(bcert, NULL);
- if (pk7cert == NULL)
- goto exit;
-
- t = OBJ_obj2nid(pk7cert->type);
- switch (t)
- {
- case NID_pkcs7_signed:
- certs = pk7cert->d.sign->cert;
- break;
-
- case NID_pkcs7_signedAndEnveloped:
- certs = pk7cert->d.sign->cert;
- break;
-
- default:
- break;
- }
-
- st = X509_STORE_new();
- if (st == NULL)
- goto exit;
-
- /* Add the certificates to the store */
- if (certs != NULL)
- {
- int i, n = sk_X509_num(certs);
-
- for (i = 0; i < n; i++)
- {
- X509 *c = sk_X509_value(certs, i);
- X509_STORE_add_cert(st, c);
- }
- }
-
- res = pk7_verify(st, pk7sig, bsegs, ebuf, ebufsize);
-
-exit:
- BIO_free(bsig);
- BIO_free(bdata);
- BIO_free(bsegs);
- BIO_free(bcert);
- PKCS7_free(pk7sig);
- PKCS7_free(pk7cert);
- X509_STORE_free(st);
-
- return res;
-}
-
-int pdf_check_signature(fz_context *ctx, pdf_document *doc, pdf_widget *widget, char *file, char *ebuf, int ebufsize)
-{
- int (*byte_range)[2] = NULL;
- int byte_range_len;
- char *contents = NULL;
- int contents_len;
- int res = 0;
-
- fz_var(byte_range);
- fz_var(res);
- fz_try(ctx);
- {
- byte_range_len = pdf_signature_widget_byte_range(doc, widget, NULL);
- if (byte_range_len)
- {
- byte_range = fz_calloc(ctx, byte_range_len, sizeof(*byte_range));
- pdf_signature_widget_byte_range(doc, widget, byte_range);
- }
-
- contents_len = pdf_signature_widget_contents(doc, widget, &contents);
- if (byte_range && contents)
- {
- res = verify_sig(contents, contents_len, file, byte_range, byte_range_len, ebuf, ebufsize);
- }
- else
- {
- res = 0;
- strncpy(ebuf, "Not signed", ebufsize);
- }
-
- }
- fz_always(ctx)
- {
- fz_free(ctx, byte_range);
- }
- fz_catch(ctx)
- {
- res = 0;
- strncpy(ebuf, fz_caught_message(ctx), ebufsize);
- }
-
- if (ebufsize > 0)
- ebuf[ebufsize-1] = 0;
-
- return res;
-}
-
-#else /* HAVE_OPENSSL */
-
-int pdf_check_signature(fz_context *ctx, pdf_document *doc, pdf_widget *widget, char *file, char *ebuf, int ebufsize)
-{
- strncpy(ebuf, "This version of MuPDF was built without signature support", ebufsize);
-
- return 0;
-}
-
-#endif /* HAVE_OPENSSL */
diff --git a/fitz/crypt_sha2.c b/fitz/crypt_sha2.c
deleted file mode 100644
index ffedfc95..00000000
--- a/fitz/crypt_sha2.c
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
-This code is based on the code found from 7-Zip, which has a modified
-version of the SHA-256 found from Crypto++ <http://www.cryptopp.com/>.
-The code was modified a little to fit into liblzma and fitz.
-
-This file has been put into the public domain.
-You can do whatever you want with this file.
-
-SHA-384 and SHA-512 were also taken from Crypto++ and adapted for fitz.
-*/
-
-#include "mupdf/fitz.h"
-
-static inline int isbigendian(void)
-{
- static const int one = 1;
- return *(char*)&one == 0;
-}
-
-static inline unsigned int bswap32(unsigned int num)
-{
- if (!isbigendian())
- {
- return ( (((num) << 24))
- | (((num) << 8) & 0x00FF0000)
- | (((num) >> 8) & 0x0000FF00)
- | (((num) >> 24)) );
- }
- return num;
-}
-
-static inline uint64_t bswap64(uint64_t num)
-{
- if (!isbigendian())
- {
- return ( (((num) << 56))
- | (((num) << 40) & 0x00FF000000000000ULL)
- | (((num) << 24) & 0x0000FF0000000000ULL)
- | (((num) << 8) & 0x000000FF00000000ULL)
- | (((num) >> 8) & 0x00000000FF000000ULL)
- | (((num) >> 24) & 0x0000000000FF0000ULL)
- | (((num) >> 40) & 0x000000000000FF00ULL)
- | (((num) >> 56)) );
- }
- return num;
-}
-
-/* At least on x86, GCC is able to optimize this to a rotate instruction. */
-#define rotr(num, amount) ((num) >> (amount) | (num) << (8 * sizeof(num) - (amount)))
-
-#define blk0(i) (W[i] = data[i])
-#define blk2(i) (W[i & 15] += s1(W[(i - 2) & 15]) + W[(i - 7) & 15] \
- + s0(W[(i - 15) & 15]))
-
-#define Ch(x, y, z) (z ^ (x & (y ^ z)))
-#define Maj(x, y, z) ((x & y) | (z & (x | y)))
-
-#define a(i) T[(0 - i) & 7]
-#define b(i) T[(1 - i) & 7]
-#define c(i) T[(2 - i) & 7]
-#define d(i) T[(3 - i) & 7]
-#define e(i) T[(4 - i) & 7]
-#define f(i) T[(5 - i) & 7]
-#define g(i) T[(6 - i) & 7]
-#define h(i) T[(7 - i) & 7]
-
-#define R(i) \
- h(i) += S1(e(i)) + Ch(e(i), f(i), g(i)) + K[i + j] \
- + (j ? blk2(i) : blk0(i)); \
- d(i) += h(i); \
- h(i) += S0(a(i)) + Maj(a(i), b(i), c(i))
-
-/* For SHA256 */
-
-#define S0(x) (rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22))
-#define S1(x) (rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25))
-#define s0(x) (rotr(x, 7) ^ rotr(x, 18) ^ (x >> 3))
-#define s1(x) (rotr(x, 17) ^ rotr(x, 19) ^ (x >> 10))
-
-static const unsigned int SHA256_K[64] = {
- 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
- 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
- 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
- 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
- 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
- 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
- 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
- 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
- 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
- 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
- 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
- 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
- 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
- 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
- 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
- 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
-};
-
-static void
-transform256(unsigned int state[8], const unsigned int data_xe[16])
-{
- const unsigned int *K = SHA256_K;
- unsigned int data[16];
- unsigned int W[16];
- unsigned int T[8];
- unsigned int j;
-
- /* ensure big-endian integers */
- for (j = 0; j < 16; j++)
- data[j] = bswap32(data_xe[j]);
-
- /* Copy state[] to working vars. */
- memcpy(T, state, sizeof(T));
-
- /* 64 operations, partially loop unrolled */
- for (j = 0; j < 64; j += 16) {
- R( 0); R( 1); R( 2); R( 3);
- R( 4); R( 5); R( 6); R( 7);
- R( 8); R( 9); R(10); R(11);
- R(12); R(13); R(14); R(15);
- }
-
- /* Add the working vars back into state[]. */
- state[0] += a(0);
- state[1] += b(0);
- state[2] += c(0);
- state[3] += d(0);
- state[4] += e(0);
- state[5] += f(0);
- state[6] += g(0);
- state[7] += h(0);
-}
-
-#undef S0
-#undef S1
-#undef s0
-#undef s1
-
-void fz_sha256_init(fz_sha256 *context)
-{
- context->count[0] = context->count[1] = 0;
-
- context->state[0] = 0x6A09E667;
- context->state[1] = 0xBB67AE85;
- context->state[2] = 0x3C6EF372;
- context->state[3] = 0xA54FF53A;
- context->state[4] = 0x510E527F;
- context->state[5] = 0x9B05688C;
- context->state[6] = 0x1F83D9AB;
- context->state[7] = 0x5BE0CD19;
-}
-
-void fz_sha256_update(fz_sha256 *context, const unsigned char *input, unsigned int inlen)
-{
- /* Copy the input data into a properly aligned temporary buffer.
- * This way we can be called with arbitrarily sized buffers
- * (no need to be multiple of 64 bytes), and the code works also
- * on architectures that don't allow unaligned memory access. */
- while (inlen > 0)
- {
- const unsigned int copy_start = context->count[0] & 0x3F;
- unsigned int copy_size = 64 - copy_start;
- if (copy_size > inlen)
- copy_size = inlen;
-
- memcpy(context->buffer.u8 + copy_start, input, copy_size);
-
- input += copy_size;
- inlen -= copy_size;
- context->count[0] += copy_size;
- /* carry overflow from low to high */
- if (context->count[0] < copy_size)
- context->count[1]++;
-
- if ((context->count[0] & 0x3F) == 0)
- transform256(context->state, context->buffer.u32);
- }
-}
-
-void fz_sha256_final(fz_sha256 *context, unsigned char digest[32])
-{
- /* Add padding as described in RFC 3174 (it describes SHA-1 but
- * the same padding style is used for SHA-256 too). */
- unsigned int j = context->count[0] & 0x3F;
- context->buffer.u8[j++] = 0x80;
-
- while (j != 56)
- {
- if (j == 64)
- {
- transform256(context->state, context->buffer.u32);
- j = 0;
- }
- context->buffer.u8[j++] = 0x00;
- }
-
- /* Convert the message size from bytes to bits. */
- context->count[1] = (context->count[1] << 3) + (context->count[0] >> 29);
- context->count[0] = context->count[0] << 3;
-
- context->buffer.u32[14] = bswap32(context->count[1]);
- context->buffer.u32[15] = bswap32(context->count[0]);
- transform256(context->state, context->buffer.u32);
-
- for (j = 0; j < 8; j++)
- ((unsigned int *)digest)[j] = bswap32(context->state[j]);
- memset(context, 0, sizeof(fz_sha256));
-}
-
-/* For SHA512 */
-
-#define S0(x) (rotr(x, 28) ^ rotr(x, 34) ^ rotr(x, 39))
-#define S1(x) (rotr(x, 14) ^ rotr(x, 18) ^ rotr(x, 41))
-#define s0(x) (rotr(x, 1) ^ rotr(x, 8) ^ (x >> 7))
-#define s1(x) (rotr(x, 19) ^ rotr(x, 61) ^ (x >> 6))
-
-static const uint64_t SHA512_K[80] = {
- 0x428A2F98D728AE22ULL, 0x7137449123EF65CDULL,
- 0xB5C0FBCFEC4D3B2FULL, 0xE9B5DBA58189DBBCULL,
- 0x3956C25BF348B538ULL, 0x59F111F1B605D019ULL,
- 0x923F82A4AF194F9BULL, 0xAB1C5ED5DA6D8118ULL,
- 0xD807AA98A3030242ULL, 0x12835B0145706FBEULL,
- 0x243185BE4EE4B28CULL, 0x550C7DC3D5FFB4E2ULL,
- 0x72BE5D74F27B896FULL, 0x80DEB1FE3B1696B1ULL,
- 0x9BDC06A725C71235ULL, 0xC19BF174CF692694ULL,
- 0xE49B69C19EF14AD2ULL, 0xEFBE4786384F25E3ULL,
- 0x0FC19DC68B8CD5B5ULL, 0x240CA1CC77AC9C65ULL,
- 0x2DE92C6F592B0275ULL, 0x4A7484AA6EA6E483ULL,
- 0x5CB0A9DCBD41FBD4ULL, 0x76F988DA831153B5ULL,
- 0x983E5152EE66DFABULL, 0xA831C66D2DB43210ULL,
- 0xB00327C898FB213FULL, 0xBF597FC7BEEF0EE4ULL,
- 0xC6E00BF33DA88FC2ULL, 0xD5A79147930AA725ULL,
- 0x06CA6351E003826FULL, 0x142929670A0E6E70ULL,
- 0x27B70A8546D22FFCULL, 0x2E1B21385C26C926ULL,
- 0x4D2C6DFC5AC42AEDULL, 0x53380D139D95B3DFULL,
- 0x650A73548BAF63DEULL, 0x766A0ABB3C77B2A8ULL,
- 0x81C2C92E47EDAEE6ULL, 0x92722C851482353BULL,
- 0xA2BFE8A14CF10364ULL, 0xA81A664BBC423001ULL,
- 0xC24B8B70D0F89791ULL, 0xC76C51A30654BE30ULL,
- 0xD192E819D6EF5218ULL, 0xD69906245565A910ULL,
- 0xF40E35855771202AULL, 0x106AA07032BBD1B8ULL,
- 0x19A4C116B8D2D0C8ULL, 0x1E376C085141AB53ULL,
- 0x2748774CDF8EEB99ULL, 0x34B0BCB5E19B48A8ULL,
- 0x391C0CB3C5C95A63ULL, 0x4ED8AA4AE3418ACBULL,
- 0x5B9CCA4F7763E373ULL, 0x682E6FF3D6B2B8A3ULL,
- 0x748F82EE5DEFB2FCULL, 0x78A5636F43172F60ULL,
- 0x84C87814A1F0AB72ULL, 0x8CC702081A6439ECULL,
- 0x90BEFFFA23631E28ULL, 0xA4506CEBDE82BDE9ULL,
- 0xBEF9A3F7B2C67915ULL, 0xC67178F2E372532BULL,
- 0xCA273ECEEA26619CULL, 0xD186B8C721C0C207ULL,
- 0xEADA7DD6CDE0EB1EULL, 0xF57D4F7FEE6ED178ULL,
- 0x06F067AA72176FBAULL, 0x0A637DC5A2C898A6ULL,
- 0x113F9804BEF90DAEULL, 0x1B710B35131C471BULL,
- 0x28DB77F523047D84ULL, 0x32CAAB7B40C72493ULL,
- 0x3C9EBE0A15C9BEBCULL, 0x431D67C49C100D4CULL,
- 0x4CC5D4BECB3E42B6ULL, 0x597F299CFC657E2AULL,
- 0x5FCB6FAB3AD6FAECULL, 0x6C44198C4A475817ULL,
-};
-
-static void
-transform512(uint64_t state[8], const uint64_t data_xe[16])
-{
- const uint64_t *K = SHA512_K;
- uint64_t data[16];
- uint64_t W[16];
- uint64_t T[8];
- unsigned int j;
-
- /* ensure big-endian integers */
- for (j = 0; j < 16; j++)
- data[j] = bswap64(data_xe[j]);
-
- /* Copy state[] to working vars. */
- memcpy(T, state, sizeof(T));
-
- /* 80 operations, partially loop unrolled */
- for (j = 0; j < 80; j+= 16) {
- R( 0); R( 1); R( 2); R( 3);
- R( 4); R( 5); R( 6); R( 7);
- R( 8); R( 9); R(10); R(11);
- R(12); R(13); R(14); R(15);
- }
-
- /* Add the working vars back into state[]. */
- state[0] += a(0);
- state[1] += b(0);
- state[2] += c(0);
- state[3] += d(0);
- state[4] += e(0);
- state[5] += f(0);
- state[6] += g(0);
- state[7] += h(0);
-}
-
-#undef S0
-#undef S1
-#undef s0
-#undef s1
-
-void fz_sha512_init(fz_sha512 *context)
-{
- context->count[0] = context->count[1] = 0;
-
- context->state[0] = 0x6A09E667F3BCC908ull;
- context->state[1] = 0xBB67AE8584CAA73Bull;
- context->state[2] = 0x3C6EF372FE94F82Bull;
- context->state[3] = 0xA54FF53A5F1D36F1ull;
- context->state[4] = 0x510E527FADE682D1ull;
- context->state[5] = 0x9B05688C2B3E6C1Full;
- context->state[6] = 0x1F83D9ABFB41BD6Bull;
- context->state[7] = 0x5BE0CD19137E2179ull;
-}
-
-void fz_sha512_update(fz_sha512 *context, const unsigned char *input, unsigned int inlen)
-{
- /* Copy the input data into a properly aligned temporary buffer.
- * This way we can be called with arbitrarily sized buffers
- * (no need to be multiple of 128 bytes), and the code works also
- * on architectures that don't allow unaligned memory access. */
- while (inlen > 0)
- {
- const unsigned int copy_start = context->count[0] & 0x7F;
- unsigned int copy_size = 128 - copy_start;
- if (copy_size > inlen)
- copy_size = inlen;
-
- memcpy(context->buffer.u8 + copy_start, input, copy_size);
-
- input += copy_size;
- inlen -= copy_size;
- context->count[0] += copy_size;
- /* carry overflow from low to high */
- if (context->count[0] < copy_size)
- context->count[1]++;
-
- if ((context->count[0] & 0x7F) == 0)
- transform512(context->state, context->buffer.u64);
- }
-}
-
-void fz_sha512_final(fz_sha512 *context, unsigned char digest[64])
-{
- /* Add padding as described in RFC 3174 (it describes SHA-1 but
- * the same padding style is used for SHA-512 too). */
- unsigned int j = context->count[0] & 0x7F;
- context->buffer.u8[j++] = 0x80;
-
- while (j != 112)
- {
- if (j == 128)
- {
- transform512(context->state, context->buffer.u64);
- j = 0;
- }
- context->buffer.u8[j++] = 0x00;
- }
-
- /* Convert the message size from bytes to bits. */
- context->count[1] = (context->count[1] << 3) + (context->count[0] >> 29);
- context->count[0] = context->count[0] << 3;
-
- context->buffer.u64[14] = bswap64(context->count[1]);
- context->buffer.u64[15] = bswap64(context->count[0]);
- transform512(context->state, context->buffer.u64);
-
- for (j = 0; j < 8; j++)
- ((uint64_t *)digest)[j] = bswap64(context->state[j]);
- memset(context, 0, sizeof(fz_sha512));
-}
-
-void fz_sha384_init(fz_sha384 *context)
-{
- context->count[0] = context->count[1] = 0;
-
- context->state[0] = 0xCBBB9D5DC1059ED8ull;
- context->state[1] = 0x629A292A367CD507ull;
- context->state[2] = 0x9159015A3070DD17ull;
- context->state[3] = 0x152FECD8F70E5939ull;
- context->state[4] = 0x67332667FFC00B31ull;
- context->state[5] = 0x8EB44A8768581511ull;
- context->state[6] = 0xDB0C2E0D64F98FA7ull;
- context->state[7] = 0x47B5481DBEFA4FA4ull;
-}
-
-void fz_sha384_update(fz_sha384 *context, const unsigned char *input, unsigned int inlen)
-{
- fz_sha512_update(context, input, inlen);
-}
-
-void fz_sha384_final(fz_sha384 *context, unsigned char digest[64])
-{
- fz_sha512_final(context, digest);
-}
diff --git a/fitz/dev_bbox.c b/fitz/dev_bbox.c
deleted file mode 100644
index 9cb2a27e..00000000
--- a/fitz/dev_bbox.c
+++ /dev/null
@@ -1,231 +0,0 @@
-#include "mupdf/fitz.h"
-
-#define STACK_SIZE 96
-
-typedef struct fz_bbox_data_s
-{
- fz_rect *result;
- int top;
- fz_rect stack[STACK_SIZE];
- /* mask content and tiles are ignored */
- int ignore;
-} fz_bbox_data;
-
-static void
-fz_bbox_add_rect(fz_device *dev, const fz_rect *rect, int clip)
-{
- fz_bbox_data *data = dev->user;
- fz_rect r = *rect;
-
- if (0 < data->top && data->top <= STACK_SIZE)
- {
- fz_intersect_rect(&r, &data->stack[data->top-1]);
- }
- if (!clip && data->top <= STACK_SIZE && !data->ignore)
- {
- fz_union_rect(data->result, &r);
- }
- if (clip && ++data->top <= STACK_SIZE)
- {
- data->stack[data->top-1] = r;
- }
-}
-
-static void
-fz_bbox_fill_path(fz_device *dev, fz_path *path, int even_odd, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- fz_rect r;
- fz_bbox_add_rect(dev, fz_bound_path(dev->ctx, path, NULL, ctm, &r), 0);
-}
-
-static void
-fz_bbox_stroke_path(fz_device *dev, fz_path *path, fz_stroke_state *stroke,
- const fz_matrix *ctm, fz_colorspace *colorspace, float *color, float alpha)
-{
- fz_rect r;
- fz_bbox_add_rect(dev, fz_bound_path(dev->ctx, path, stroke, ctm, &r), 0);
-}
-
-static void
-fz_bbox_fill_text(fz_device *dev, fz_text *text, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- fz_rect r;
- fz_bbox_add_rect(dev, fz_bound_text(dev->ctx, text, NULL, ctm, &r), 0);
-}
-
-static void
-fz_bbox_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke,
- const fz_matrix *ctm, fz_colorspace *colorspace, float *color, float alpha)
-{
- fz_rect r;
- fz_bbox_add_rect(dev, fz_bound_text(dev->ctx, text, stroke, ctm, &r), 0);
-}
-
-static void
-fz_bbox_fill_shade(fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha)
-{
- fz_rect r;
- fz_bbox_add_rect(dev, fz_bound_shade(dev->ctx, shade, ctm, &r), 0);
-}
-
-static void
-fz_bbox_fill_image(fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha)
-{
- fz_rect r = fz_unit_rect;
- fz_bbox_add_rect(dev, fz_transform_rect(&r, ctm), 0);
-}
-
-static void
-fz_bbox_fill_image_mask(fz_device *dev, fz_image *image, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- fz_rect r = fz_unit_rect;
- fz_bbox_add_rect(dev, fz_transform_rect(&r, ctm), 0);
-}
-
-static void
-fz_bbox_clip_path(fz_device *dev, fz_path *path, const fz_rect *rect, int even_odd, const fz_matrix *ctm)
-{
- fz_rect r;
- fz_bbox_add_rect(dev, fz_bound_path(dev->ctx, path, NULL, ctm, &r), 1);
-}
-
-static void
-fz_bbox_clip_stroke_path(fz_device *dev, fz_path *path, const fz_rect *rect, fz_stroke_state *stroke, const fz_matrix *ctm)
-{
- fz_rect r;
- fz_bbox_add_rect(dev, fz_bound_path(dev->ctx, path, stroke, ctm, &r), 1);
-}
-
-static void
-fz_bbox_clip_text(fz_device *dev, fz_text *text, const fz_matrix *ctm, int accumulate)
-{
- fz_rect r = fz_infinite_rect;
- if (accumulate)
- fz_bbox_add_rect(dev, &r, accumulate != 2);
- else
- fz_bbox_add_rect(dev, fz_bound_text(dev->ctx, text, NULL, ctm, &r), 1);
-}
-
-static void
-fz_bbox_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, const fz_matrix *ctm)
-{
- fz_rect r;
- fz_bbox_add_rect(dev, fz_bound_text(dev->ctx, text, stroke, ctm, &r), 1);
-}
-
-static void
-fz_bbox_clip_image_mask(fz_device *dev, fz_image *image, const fz_rect *rect, const fz_matrix *ctm)
-{
- fz_rect r = *rect;
- fz_bbox_add_rect(dev, fz_transform_rect(&r, ctm), 1);
-}
-
-static void
-fz_bbox_pop_clip(fz_device *dev)
-{
- fz_bbox_data *data = dev->user;
- if (data->top > 0)
- data->top--;
- else
- fz_warn(dev->ctx, "unexpected pop clip");
-}
-
-static void
-fz_bbox_begin_mask(fz_device *dev, const fz_rect *rect, int luminosity, fz_colorspace *colorspace, float *color)
-{
- fz_bbox_data *data = dev->user;
- fz_bbox_add_rect(dev, rect, 1);
- data->ignore++;
-}
-
-static void
-fz_bbox_end_mask(fz_device *dev)
-{
- fz_bbox_data *data = dev->user;
- assert(data->ignore > 0);
- data->ignore--;
-}
-
-static void
-fz_bbox_begin_group(fz_device *dev, const fz_rect *rect, int isolated, int knockout, int blendmode, float alpha)
-{
- fz_bbox_add_rect(dev, rect, 1);
-}
-
-static void
-fz_bbox_end_group(fz_device *dev)
-{
- fz_bbox_pop_clip(dev);
-}
-
-static int
-fz_bbox_begin_tile(fz_device *dev, const fz_rect *area, const fz_rect *view, float xstep, float ystep, const fz_matrix *ctm, int id)
-{
- fz_bbox_data *data = dev->user;
- fz_rect r = *area;
- fz_bbox_add_rect(dev, fz_transform_rect(&r, ctm), 0);
- data->ignore++;
- return 0;
-}
-
-static void
-fz_bbox_end_tile(fz_device *dev)
-{
- fz_bbox_data *data = dev->user;
- assert(data->ignore > 0);
- data->ignore--;
-}
-
-static void
-fz_bbox_free_user(fz_device *dev)
-{
- fz_bbox_data *data = dev->user;
- if (data->top > 0)
- fz_warn(dev->ctx, "items left on stack in bbox device: %d", data->top);
- fz_free(dev->ctx, dev->user);
-}
-
-fz_device *
-fz_new_bbox_device(fz_context *ctx, fz_rect *result)
-{
- fz_device *dev;
-
- fz_bbox_data *user = fz_malloc_struct(ctx, fz_bbox_data);
- user->result = result;
- user->top = 0;
- user->ignore = 0;
- dev = fz_new_device(ctx, user);
- dev->free_user = fz_bbox_free_user;
-
- dev->fill_path = fz_bbox_fill_path;
- dev->stroke_path = fz_bbox_stroke_path;
- dev->clip_path = fz_bbox_clip_path;
- dev->clip_stroke_path = fz_bbox_clip_stroke_path;
-
- dev->fill_text = fz_bbox_fill_text;
- dev->stroke_text = fz_bbox_stroke_text;
- dev->clip_text = fz_bbox_clip_text;
- dev->clip_stroke_text = fz_bbox_clip_stroke_text;
-
- dev->fill_shade = fz_bbox_fill_shade;
- dev->fill_image = fz_bbox_fill_image;
- dev->fill_image_mask = fz_bbox_fill_image_mask;
- dev->clip_image_mask = fz_bbox_clip_image_mask;
-
- dev->pop_clip = fz_bbox_pop_clip;
-
- dev->begin_mask = fz_bbox_begin_mask;
- dev->end_mask = fz_bbox_end_mask;
- dev->begin_group = fz_bbox_begin_group;
- dev->end_group = fz_bbox_end_group;
-
- dev->begin_tile = fz_bbox_begin_tile;
- dev->end_tile = fz_bbox_end_tile;
-
- *result = fz_empty_rect;
-
- return dev;
-}
diff --git a/fitz/dev_list.c b/fitz/dev_list.c
deleted file mode 100644
index 6ffe165f..00000000
--- a/fitz/dev_list.c
+++ /dev/null
@@ -1,851 +0,0 @@
-#include "mupdf/fitz.h"
-
-typedef struct fz_display_node_s fz_display_node;
-
-#define STACK_SIZE 96
-
-typedef enum fz_display_command_e
-{
- FZ_CMD_BEGIN_PAGE,
- FZ_CMD_END_PAGE,
- FZ_CMD_FILL_PATH,
- FZ_CMD_STROKE_PATH,
- FZ_CMD_CLIP_PATH,
- FZ_CMD_CLIP_STROKE_PATH,
- FZ_CMD_FILL_TEXT,
- FZ_CMD_STROKE_TEXT,
- FZ_CMD_CLIP_TEXT,
- FZ_CMD_CLIP_STROKE_TEXT,
- FZ_CMD_IGNORE_TEXT,
- FZ_CMD_FILL_SHADE,
- FZ_CMD_FILL_IMAGE,
- FZ_CMD_FILL_IMAGE_MASK,
- FZ_CMD_CLIP_IMAGE_MASK,
- FZ_CMD_POP_CLIP,
- FZ_CMD_BEGIN_MASK,
- FZ_CMD_END_MASK,
- FZ_CMD_BEGIN_GROUP,
- FZ_CMD_END_GROUP,
- FZ_CMD_BEGIN_TILE,
- FZ_CMD_END_TILE
-} fz_display_command;
-
-struct fz_display_node_s
-{
- fz_display_command cmd;
- fz_display_node *next;
- fz_rect rect;
- union {
- fz_path *path;
- fz_text *text;
- fz_shade *shade;
- fz_image *image;
- int blendmode;
- } item;
- fz_stroke_state *stroke;
- int flag; /* even_odd, accumulate, isolated/knockout... */
- fz_matrix ctm;
- fz_colorspace *colorspace;
- float alpha;
- float color[FZ_MAX_COLORS];
-};
-
-struct fz_display_list_s
-{
- fz_storable storable;
- fz_display_node *first;
- fz_display_node *last;
- int len;
-
- int top;
- struct {
- fz_rect *update;
- fz_rect rect;
- } stack[STACK_SIZE];
- int tiled;
-};
-
-enum { ISOLATED = 1, KNOCKOUT = 2 };
-
-static fz_display_node *
-fz_new_display_node(fz_context *ctx, fz_display_command cmd, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- fz_display_node *node;
- int i;
-
- node = fz_malloc_struct(ctx, fz_display_node);
- node->cmd = cmd;
- node->next = NULL;
- node->rect = fz_empty_rect;
- node->item.path = NULL;
- node->stroke = NULL;
- node->flag = (cmd == FZ_CMD_BEGIN_TILE ? fz_gen_id(ctx) : 0);
- node->ctm = *ctm;
- if (colorspace)
- {
- node->colorspace = fz_keep_colorspace(ctx, colorspace);
- if (color)
- {
- for (i = 0; i < node->colorspace->n; i++)
- node->color[i] = color[i];
- }
- }
- else
- {
- node->colorspace = NULL;
- }
- node->alpha = alpha;
-
- return node;
-}
-
-static void
-fz_append_display_node(fz_display_list *list, fz_display_node *node)
-{
- switch (node->cmd)
- {
- case FZ_CMD_CLIP_PATH:
- case FZ_CMD_CLIP_STROKE_PATH:
- case FZ_CMD_CLIP_IMAGE_MASK:
- if (list->top < STACK_SIZE)
- {
- list->stack[list->top].update = &node->rect;
- list->stack[list->top].rect = fz_empty_rect;
- }
- list->top++;
- break;
- case FZ_CMD_END_MASK:
- case FZ_CMD_CLIP_TEXT:
- case FZ_CMD_CLIP_STROKE_TEXT:
- if (list->top < STACK_SIZE)
- {
- list->stack[list->top].update = NULL;
- list->stack[list->top].rect = fz_empty_rect;
- }
- list->top++;
- break;
- case FZ_CMD_BEGIN_TILE:
- list->tiled++;
- if (list->top > 0 && list->top <= STACK_SIZE)
- {
- list->stack[list->top-1].rect = fz_infinite_rect;
- }
- break;
- case FZ_CMD_END_TILE:
- list->tiled--;
- break;
- case FZ_CMD_END_GROUP:
- break;
- case FZ_CMD_POP_CLIP:
- if (list->top > STACK_SIZE)
- {
- list->top--;
- node->rect = fz_infinite_rect;
- }
- else if (list->top > 0)
- {
- fz_rect *update;
- list->top--;
- update = list->stack[list->top].update;
- if (list->tiled == 0)
- {
- if (update)
- {
- fz_intersect_rect(update, &list->stack[list->top].rect);
- node->rect = *update;
- }
- else
- node->rect = list->stack[list->top].rect;
- }
- else
- node->rect = fz_infinite_rect;
- }
- /* fallthrough */
- default:
- if (list->top > 0 && list->tiled == 0 && list->top <= STACK_SIZE)
- fz_union_rect(&list->stack[list->top-1].rect, &node->rect);
- break;
- }
- if (!list->first)
- {
- list->first = node;
- list->last = node;
- }
- else
- {
- list->last->next = node;
- list->last = node;
- }
- list->len++;
-}
-
-static void
-fz_free_display_node(fz_context *ctx, fz_display_node *node)
-{
- switch (node->cmd)
- {
- case FZ_CMD_FILL_PATH:
- case FZ_CMD_STROKE_PATH:
- case FZ_CMD_CLIP_PATH:
- case FZ_CMD_CLIP_STROKE_PATH:
- fz_free_path(ctx, node->item.path);
- break;
- case FZ_CMD_FILL_TEXT:
- case FZ_CMD_STROKE_TEXT:
- case FZ_CMD_CLIP_TEXT:
- case FZ_CMD_CLIP_STROKE_TEXT:
- case FZ_CMD_IGNORE_TEXT:
- fz_free_text(ctx, node->item.text);
- break;
- case FZ_CMD_FILL_SHADE:
- fz_drop_shade(ctx, node->item.shade);
- break;
- case FZ_CMD_FILL_IMAGE:
- case FZ_CMD_FILL_IMAGE_MASK:
- case FZ_CMD_CLIP_IMAGE_MASK:
- fz_drop_image(ctx, node->item.image);
- break;
- case FZ_CMD_POP_CLIP:
- case FZ_CMD_BEGIN_MASK:
- case FZ_CMD_END_MASK:
- case FZ_CMD_BEGIN_GROUP:
- case FZ_CMD_END_GROUP:
- case FZ_CMD_BEGIN_TILE:
- case FZ_CMD_END_TILE:
- case FZ_CMD_BEGIN_PAGE:
- case FZ_CMD_END_PAGE:
- break;
- }
- if (node->stroke)
- fz_drop_stroke_state(ctx, node->stroke);
- if (node->colorspace)
- fz_drop_colorspace(ctx, node->colorspace);
- fz_free(ctx, node);
-}
-
-static void
-fz_list_begin_page(fz_device *dev, const fz_rect *mediabox, const fz_matrix *ctm)
-{
- fz_context *ctx = dev->ctx;
- fz_display_node *node = fz_new_display_node(ctx, FZ_CMD_BEGIN_PAGE, ctm, NULL, NULL, 0);
- node->rect = *mediabox;
- fz_transform_rect(&node->rect, ctm);
- fz_append_display_node(dev->user, node);
-}
-
-static void
-fz_list_end_page(fz_device *dev)
-{
- fz_context *ctx = dev->ctx;
- fz_display_node *node = fz_new_display_node(ctx, FZ_CMD_END_PAGE, &fz_identity, NULL, NULL, 0);
- fz_append_display_node(dev->user, node);
-}
-
-static void
-fz_list_fill_path(fz_device *dev, fz_path *path, int even_odd, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- fz_display_node *node;
- fz_context *ctx = dev->ctx;
- node = fz_new_display_node(ctx, FZ_CMD_FILL_PATH, ctm, colorspace, color, alpha);
- fz_try(ctx)
- {
- fz_bound_path(dev->ctx, path, NULL, ctm, &node->rect);
- node->item.path = fz_clone_path(dev->ctx, path);
- node->flag = even_odd;
- }
- fz_catch(ctx)
- {
- fz_free_display_node(ctx, node);
- fz_rethrow(ctx);
- }
- fz_append_display_node(dev->user, node);
-}
-
-static void
-fz_list_stroke_path(fz_device *dev, fz_path *path, fz_stroke_state *stroke,
- const fz_matrix *ctm, fz_colorspace *colorspace, float *color, float alpha)
-{
- fz_display_node *node;
- fz_context *ctx = dev->ctx;
- node = fz_new_display_node(ctx, FZ_CMD_STROKE_PATH, ctm, colorspace, color, alpha);
- fz_try(ctx)
- {
- fz_bound_path(dev->ctx, path, stroke, ctm, &node->rect);
- node->item.path = fz_clone_path(dev->ctx, path);
- node->stroke = fz_keep_stroke_state(dev->ctx, stroke);
- }
- fz_catch(ctx)
- {
- fz_free_display_node(ctx, node);
- fz_rethrow(ctx);
- }
- fz_append_display_node(dev->user, node);
-}
-
-static void
-fz_list_clip_path(fz_device *dev, fz_path *path, const fz_rect *rect, int even_odd, const fz_matrix *ctm)
-{
- fz_display_node *node;
- fz_context *ctx = dev->ctx;
- node = fz_new_display_node(ctx, FZ_CMD_CLIP_PATH, ctm, NULL, NULL, 0);
- fz_try(ctx)
- {
- fz_bound_path(dev->ctx, path, NULL, ctm, &node->rect);
- if (rect)
- fz_intersect_rect(&node->rect, rect);
- node->item.path = fz_clone_path(dev->ctx, path);
- node->flag = even_odd;
- }
- fz_catch(ctx)
- {
- fz_free_display_node(ctx, node);
- fz_rethrow(ctx);
- }
- fz_append_display_node(dev->user, node);
-}
-
-static void
-fz_list_clip_stroke_path(fz_device *dev, fz_path *path, const fz_rect *rect, fz_stroke_state *stroke, const fz_matrix *ctm)
-{
- fz_display_node *node;
- fz_context *ctx = dev->ctx;
- node = fz_new_display_node(ctx, FZ_CMD_CLIP_STROKE_PATH, ctm, NULL, NULL, 0);
- fz_try(ctx)
- {
- fz_bound_path(dev->ctx, path, stroke, ctm, &node->rect);
- if (rect)
- fz_intersect_rect(&node->rect, rect);
- node->item.path = fz_clone_path(dev->ctx, path);
- node->stroke = fz_keep_stroke_state(dev->ctx, stroke);
- }
- fz_catch(ctx)
- {
- fz_free_display_node(ctx, node);
- fz_rethrow(ctx);
- }
- fz_append_display_node(dev->user, node);
-}
-
-static void
-fz_list_fill_text(fz_device *dev, fz_text *text, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- fz_display_node *node;
- fz_context *ctx = dev->ctx;
- node = fz_new_display_node(ctx, FZ_CMD_FILL_TEXT, ctm, colorspace, color, alpha);
- fz_try(ctx)
- {
- fz_bound_text(dev->ctx, text, NULL, ctm, &node->rect);
- node->item.text = fz_clone_text(dev->ctx, text);
- }
- fz_catch(ctx)
- {
- fz_free_display_node(ctx, node);
- fz_rethrow(ctx);
- }
- fz_append_display_node(dev->user, node);
-}
-
-static void
-fz_list_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- fz_display_node *node;
- fz_context *ctx = dev->ctx;
- node = fz_new_display_node(ctx, FZ_CMD_STROKE_TEXT, ctm, colorspace, color, alpha);
- node->item.text = NULL;
- fz_try(ctx)
- {
- fz_bound_text(dev->ctx, text, stroke, ctm, &node->rect);
- node->item.text = fz_clone_text(dev->ctx, text);
- node->stroke = fz_keep_stroke_state(dev->ctx, stroke);
- }
- fz_catch(ctx)
- {
- fz_free_display_node(ctx, node);
- fz_rethrow(ctx);
- }
- fz_append_display_node(dev->user, node);
-}
-
-static void
-fz_list_clip_text(fz_device *dev, fz_text *text, const fz_matrix *ctm, int accumulate)
-{
- fz_display_node *node;
- fz_context *ctx = dev->ctx;
- node = fz_new_display_node(ctx, FZ_CMD_CLIP_TEXT, ctm, NULL, NULL, 0);
- fz_try(ctx)
- {
- fz_bound_text(dev->ctx, text, NULL, ctm, &node->rect);
- node->item.text = fz_clone_text(dev->ctx, text);
- node->flag = accumulate;
- /* when accumulating, be conservative about culling */
- if (accumulate)
- node->rect = fz_infinite_rect;
- }
- fz_catch(ctx)
- {
- fz_free_display_node(ctx, node);
- fz_rethrow(ctx);
- }
- fz_append_display_node(dev->user, node);
-}
-
-static void
-fz_list_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, const fz_matrix *ctm)
-{
- fz_display_node *node;
- fz_context *ctx = dev->ctx;
- node = fz_new_display_node(ctx, FZ_CMD_CLIP_STROKE_TEXT, ctm, NULL, NULL, 0);
- fz_try(ctx)
- {
- fz_bound_text(dev->ctx, text, stroke, ctm, &node->rect);
- node->item.text = fz_clone_text(dev->ctx, text);
- node->stroke = fz_keep_stroke_state(dev->ctx, stroke);
- }
- fz_catch(ctx)
- {
- fz_free_display_node(ctx, node);
- fz_rethrow(ctx);
- }
- fz_append_display_node(dev->user, node);
-}
-
-static void
-fz_list_ignore_text(fz_device *dev, fz_text *text, const fz_matrix *ctm)
-{
- fz_display_node *node;
- fz_context *ctx = dev->ctx;
- node = fz_new_display_node(ctx, FZ_CMD_IGNORE_TEXT, ctm, NULL, NULL, 0);
- fz_try(ctx)
- {
- fz_bound_text(dev->ctx, text, NULL, ctm, &node->rect);
- node->item.text = fz_clone_text(dev->ctx, text);
- }
- fz_catch(ctx)
- {
- fz_free_display_node(ctx, node);
- fz_rethrow(ctx);
- }
- fz_append_display_node(dev->user, node);
-}
-
-static void
-fz_list_pop_clip(fz_device *dev)
-{
- fz_display_node *node;
- node = fz_new_display_node(dev->ctx, FZ_CMD_POP_CLIP, &fz_identity, NULL, NULL, 0);
- fz_append_display_node(dev->user, node);
-}
-
-static void
-fz_list_fill_shade(fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha)
-{
- fz_display_node *node;
- fz_context *ctx = dev->ctx;
- node = fz_new_display_node(ctx, FZ_CMD_FILL_SHADE, ctm, NULL, NULL, alpha);
- fz_bound_shade(ctx, shade, ctm, &node->rect);
- node->item.shade = fz_keep_shade(ctx, shade);
- fz_append_display_node(dev->user, node);
-}
-
-static void
-fz_list_fill_image(fz_device *dev, fz_image *image, const 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_unit_rect;
- fz_transform_rect(&node->rect, ctm);
- 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_image *image, const 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_unit_rect;
- fz_transform_rect(&node->rect, ctm);
- 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_image *image, const fz_rect *rect, const 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_unit_rect;
- fz_transform_rect(&node->rect, ctm);
- if (rect)
- fz_intersect_rect(&node->rect, rect);
- node->item.image = fz_keep_image(dev->ctx, image);
- fz_append_display_node(dev->user, node);
-}
-
-static void
-fz_list_begin_mask(fz_device *dev, const fz_rect *rect, int luminosity, fz_colorspace *colorspace, float *color)
-{
- fz_display_node *node;
- node = fz_new_display_node(dev->ctx, FZ_CMD_BEGIN_MASK, &fz_identity, colorspace, color, 0);
- node->rect = *rect;
- node->flag = luminosity;
- fz_append_display_node(dev->user, node);
-}
-
-static void
-fz_list_end_mask(fz_device *dev)
-{
- fz_display_node *node;
- node = fz_new_display_node(dev->ctx, FZ_CMD_END_MASK, &fz_identity, NULL, NULL, 0);
- fz_append_display_node(dev->user, node);
-}
-
-static void
-fz_list_begin_group(fz_device *dev, const fz_rect *rect, int isolated, int knockout, int blendmode, float alpha)
-{
- fz_display_node *node;
- node = fz_new_display_node(dev->ctx, FZ_CMD_BEGIN_GROUP, &fz_identity, NULL, NULL, alpha);
- node->rect = *rect;
- node->item.blendmode = blendmode;
- node->flag |= isolated ? ISOLATED : 0;
- node->flag |= knockout ? KNOCKOUT : 0;
- fz_append_display_node(dev->user, node);
-}
-
-static void
-fz_list_end_group(fz_device *dev)
-{
- fz_display_node *node;
- node = fz_new_display_node(dev->ctx, FZ_CMD_END_GROUP, &fz_identity, NULL, NULL, 0);
- fz_append_display_node(dev->user, node);
-}
-
-static int
-fz_list_begin_tile(fz_device *dev, const fz_rect *area, const fz_rect *view, float xstep, float ystep, const fz_matrix *ctm, int id)
-{
- /* We ignore id here, as we will pass on our own id */
- fz_display_node *node;
- node = fz_new_display_node(dev->ctx, FZ_CMD_BEGIN_TILE, ctm, NULL, NULL, 0);
- node->rect = *area;
- node->color[0] = xstep;
- node->color[1] = ystep;
- node->color[2] = view->x0;
- node->color[3] = view->y0;
- node->color[4] = view->x1;
- node->color[5] = view->y1;
- fz_append_display_node(dev->user, node);
- return 0;
-}
-
-static void
-fz_list_end_tile(fz_device *dev)
-{
- fz_display_node *node;
- node = fz_new_display_node(dev->ctx, FZ_CMD_END_TILE, &fz_identity, NULL, NULL, 0);
- fz_append_display_node(dev->user, node);
-}
-
-fz_device *
-fz_new_list_device(fz_context *ctx, fz_display_list *list)
-{
- fz_device *dev = fz_new_device(ctx, list);
-
- dev->begin_page = fz_list_begin_page;
- dev->end_page = fz_list_end_page;
-
- dev->fill_path = fz_list_fill_path;
- dev->stroke_path = fz_list_stroke_path;
- dev->clip_path = fz_list_clip_path;
- dev->clip_stroke_path = fz_list_clip_stroke_path;
-
- dev->fill_text = fz_list_fill_text;
- dev->stroke_text = fz_list_stroke_text;
- dev->clip_text = fz_list_clip_text;
- dev->clip_stroke_text = fz_list_clip_stroke_text;
- dev->ignore_text = fz_list_ignore_text;
-
- dev->fill_shade = fz_list_fill_shade;
- dev->fill_image = fz_list_fill_image;
- dev->fill_image_mask = fz_list_fill_image_mask;
- dev->clip_image_mask = fz_list_clip_image_mask;
-
- dev->pop_clip = fz_list_pop_clip;
-
- dev->begin_mask = fz_list_begin_mask;
- dev->end_mask = fz_list_end_mask;
- dev->begin_group = fz_list_begin_group;
- dev->end_group = fz_list_end_group;
-
- dev->begin_tile = fz_list_begin_tile;
- dev->end_tile = fz_list_end_tile;
-
- return dev;
-}
-
-static void
-fz_free_display_list(fz_context *ctx, fz_storable *list_)
-{
- fz_display_list *list = (fz_display_list *)list_;
- fz_display_node *node;
-
- if (list == NULL)
- return;
- node = list->first;
- while (node)
- {
- fz_display_node *next = node->next;
- fz_free_display_node(ctx, node);
- node = next;
- }
- fz_free(ctx, list);
-}
-
-fz_display_list *
-fz_new_display_list(fz_context *ctx)
-{
- fz_display_list *list = fz_malloc_struct(ctx, fz_display_list);
- FZ_INIT_STORABLE(list, 1, fz_free_display_list);
- list->first = NULL;
- list->last = NULL;
- list->len = 0;
- list->top = 0;
- list->tiled = 0;
- return list;
-}
-
-fz_display_list *
-fz_keep_display_list(fz_context *ctx, fz_display_list *list)
-{
- return (fz_display_list *)fz_keep_storable(ctx, &list->storable);
-}
-
-void
-fz_drop_display_list(fz_context *ctx, fz_display_list *list)
-{
- fz_drop_storable(ctx, &list->storable);
-}
-
-static fz_display_node *
-skip_to_end_tile(fz_display_node *node, int *progress)
-{
- fz_display_node *next;
- int depth = 1;
-
- /* Skip through until we find the matching end_tile. Note that
- * (somewhat nastily) we return the PREVIOUS node to this to help
- * the calling routine. */
- do
- {
- next = node->next;
- if (next == NULL)
- break;
- if (next->cmd == FZ_CMD_BEGIN_TILE)
- depth++;
- else if (next->cmd == FZ_CMD_END_TILE)
- {
- depth--;
- if (depth == 0)
- return node;
- }
- (*progress)++;
- node = next;
- }
- while (1);
-
- return NULL;
-}
-
-void
-fz_run_display_list(fz_display_list *list, fz_device *dev, const fz_matrix *top_ctm, const fz_rect *scissor, fz_cookie *cookie)
-{
- fz_display_node *node;
- fz_matrix ctm;
- int clipped = 0;
- int tiled = 0;
- int progress = 0;
- fz_context *ctx = dev->ctx;
-
- if (!scissor)
- scissor = &fz_infinite_rect;
-
- if (cookie)
- {
- cookie->progress_max = list->len;
- cookie->progress = 0;
- }
-
- for (node = list->first; node; node = node->next)
- {
- int empty;
-
- fz_rect node_rect = node->rect;
- fz_transform_rect(&node_rect, top_ctm);
-
- /* Check the cookie for aborting */
- if (cookie)
- {
- if (cookie->abort)
- break;
- cookie->progress = progress++;
- }
-
- /* cull objects to draw using a quick visibility test */
-
- if (tiled ||
- node->cmd == FZ_CMD_BEGIN_TILE || node->cmd == FZ_CMD_END_TILE ||
- node->cmd == FZ_CMD_BEGIN_PAGE || node->cmd == FZ_CMD_END_PAGE)
- {
- empty = 0;
- }
- else
- {
- fz_rect rect = node_rect;
- fz_intersect_rect(&rect, scissor);
- empty = fz_is_empty_rect(&rect);
- }
-
- if (clipped || empty)
- {
- switch (node->cmd)
- {
- case FZ_CMD_CLIP_PATH:
- case FZ_CMD_CLIP_STROKE_PATH:
- case FZ_CMD_CLIP_STROKE_TEXT:
- case FZ_CMD_CLIP_IMAGE_MASK:
- case FZ_CMD_BEGIN_MASK:
- case FZ_CMD_BEGIN_GROUP:
- clipped++;
- continue;
- case FZ_CMD_CLIP_TEXT:
- /* Accumulated text has no extra pops */
- if (node->flag != 2)
- clipped++;
- continue;
- case FZ_CMD_POP_CLIP:
- case FZ_CMD_END_GROUP:
- if (!clipped)
- goto visible;
- clipped--;
- continue;
- case FZ_CMD_END_MASK:
- if (!clipped)
- goto visible;
- continue;
- default:
- continue;
- }
- }
-
-visible:
- fz_concat(&ctm, &node->ctm, top_ctm);
-
-
- fz_try(ctx)
- {
- switch (node->cmd)
- {
- case FZ_CMD_BEGIN_PAGE:
- fz_begin_page(dev, &node_rect, &ctm);
- break;
- case FZ_CMD_END_PAGE:
- fz_end_page(dev);
- break;
- case FZ_CMD_FILL_PATH:
- fz_fill_path(dev, node->item.path, node->flag, &ctm,
- node->colorspace, node->color, node->alpha);
- break;
- case FZ_CMD_STROKE_PATH:
- fz_stroke_path(dev, node->item.path, node->stroke, &ctm,
- node->colorspace, node->color, node->alpha);
- break;
- case FZ_CMD_CLIP_PATH:
- fz_clip_path(dev, node->item.path, &node_rect, node->flag, &ctm);
- break;
- case FZ_CMD_CLIP_STROKE_PATH:
- fz_clip_stroke_path(dev, node->item.path, &node_rect, node->stroke, &ctm);
- break;
- case FZ_CMD_FILL_TEXT:
- fz_fill_text(dev, node->item.text, &ctm,
- node->colorspace, node->color, node->alpha);
- break;
- case FZ_CMD_STROKE_TEXT:
- fz_stroke_text(dev, node->item.text, node->stroke, &ctm,
- node->colorspace, node->color, node->alpha);
- break;
- case FZ_CMD_CLIP_TEXT:
- fz_clip_text(dev, node->item.text, &ctm, node->flag);
- break;
- case FZ_CMD_CLIP_STROKE_TEXT:
- fz_clip_stroke_text(dev, node->item.text, node->stroke, &ctm);
- break;
- case FZ_CMD_IGNORE_TEXT:
- fz_ignore_text(dev, node->item.text, &ctm);
- break;
- case FZ_CMD_FILL_SHADE:
- if ((dev->hints & FZ_IGNORE_SHADE) == 0)
- fz_fill_shade(dev, node->item.shade, &ctm, node->alpha);
- break;
- case FZ_CMD_FILL_IMAGE:
- if ((dev->hints & FZ_IGNORE_IMAGE) == 0)
- fz_fill_image(dev, node->item.image, &ctm, node->alpha);
- break;
- case FZ_CMD_FILL_IMAGE_MASK:
- if ((dev->hints & FZ_IGNORE_IMAGE) == 0)
- fz_fill_image_mask(dev, node->item.image, &ctm,
- node->colorspace, node->color, node->alpha);
- break;
- case FZ_CMD_CLIP_IMAGE_MASK:
- if ((dev->hints & FZ_IGNORE_IMAGE) == 0)
- fz_clip_image_mask(dev, node->item.image, &node_rect, &ctm);
- break;
- case FZ_CMD_POP_CLIP:
- fz_pop_clip(dev);
- break;
- case FZ_CMD_BEGIN_MASK:
- fz_begin_mask(dev, &node_rect, node->flag, node->colorspace, node->color);
- break;
- case FZ_CMD_END_MASK:
- fz_end_mask(dev);
- break;
- case FZ_CMD_BEGIN_GROUP:
- fz_begin_group(dev, &node_rect,
- (node->flag & ISOLATED) != 0, (node->flag & KNOCKOUT) != 0,
- node->item.blendmode, node->alpha);
- break;
- case FZ_CMD_END_GROUP:
- fz_end_group(dev);
- break;
- case FZ_CMD_BEGIN_TILE:
- {
- int cached;
- fz_rect tile_rect;
- tiled++;
- tile_rect.x0 = node->color[2];
- tile_rect.y0 = node->color[3];
- tile_rect.x1 = node->color[4];
- tile_rect.y1 = node->color[5];
- cached = fz_begin_tile_id(dev, &node->rect, &tile_rect, node->color[0], node->color[1], &ctm, node->flag);
- if (cached)
- node = skip_to_end_tile(node, &progress);
- break;
- }
- case FZ_CMD_END_TILE:
- tiled--;
- fz_end_tile(dev);
- break;
- }
- }
- fz_catch(ctx)
- {
- /* Swallow the error */
- if (cookie)
- cookie->errors++;
- fz_warn(ctx, "Ignoring error during interpretation");
- }
- }
-}
diff --git a/fitz/dev_null.c b/fitz/dev_null.c
deleted file mode 100644
index 175b00db..00000000
--- a/fitz/dev_null.c
+++ /dev/null
@@ -1,388 +0,0 @@
-#include "mupdf/fitz.h"
-
-fz_device *
-fz_new_device(fz_context *ctx, void *user)
-{
- fz_device *dev = fz_malloc_struct(ctx, fz_device);
- dev->hints = 0;
- dev->flags = 0;
- dev->user = user;
- dev->ctx = ctx;
- dev->error_depth = 0;
- return dev;
-}
-
-void
-fz_free_device(fz_device *dev)
-{
- if (dev == NULL)
- return;
- if (dev->free_user)
- dev->free_user(dev);
- fz_free(dev->ctx, dev);
-}
-
-void
-fz_enable_device_hints(fz_device *dev, int hints)
-{
- dev->hints |= hints;
-}
-
-void
-fz_disable_device_hints(fz_device *dev, int hints)
-{
- dev->hints &= ~hints;
-}
-
-void
-fz_begin_page(fz_device *dev, const fz_rect *rect, const fz_matrix *ctm)
-{
- if (dev->begin_page)
- dev->begin_page(dev, rect, ctm);
-}
-
-void
-fz_end_page(fz_device *dev)
-{
- if (dev->end_page)
- dev->end_page(dev);
-}
-
-void
-fz_fill_path(fz_device *dev, fz_path *path, int even_odd, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- if (dev->error_depth)
- return;
- if (dev->fill_path)
- dev->fill_path(dev, path, even_odd, ctm, colorspace, color, alpha);
-}
-
-void
-fz_stroke_path(fz_device *dev, fz_path *path, fz_stroke_state *stroke, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- if (dev->error_depth)
- return;
- if (dev->stroke_path)
- dev->stroke_path(dev, path, stroke, ctm, colorspace, color, alpha);
-}
-
-void
-fz_clip_path(fz_device *dev, fz_path *path, const fz_rect *rect, int even_odd, const fz_matrix *ctm)
-{
- fz_context *ctx = dev->ctx;
-
- if (dev->error_depth)
- {
- dev->error_depth++;
- return;
- }
-
- fz_try(ctx)
- {
- if (dev->clip_path)
- dev->clip_path(dev, path, rect, even_odd, ctm);
- }
- fz_catch(ctx)
- {
- dev->error_depth = 1;
- strcpy(dev->errmess, fz_caught_message(ctx));
- /* Error swallowed */
- }
-}
-
-void
-fz_clip_stroke_path(fz_device *dev, fz_path *path, const fz_rect *rect, fz_stroke_state *stroke, const fz_matrix *ctm)
-{
- fz_context *ctx = dev->ctx;
-
- if (dev->error_depth)
- {
- dev->error_depth++;
- return;
- }
-
- fz_try(ctx)
- {
- if (dev->clip_stroke_path)
- dev->clip_stroke_path(dev, path, rect, stroke, ctm);
- }
- fz_catch(ctx)
- {
- dev->error_depth = 1;
- strcpy(dev->errmess, fz_caught_message(ctx));
- /* Error swallowed */
- }
-}
-
-void
-fz_fill_text(fz_device *dev, fz_text *text, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- if (dev->error_depth)
- return;
- if (dev->fill_text)
- dev->fill_text(dev, text, ctm, colorspace, color, alpha);
-}
-
-void
-fz_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- if (dev->error_depth)
- return;
- if (dev->stroke_text)
- dev->stroke_text(dev, text, stroke, ctm, colorspace, color, alpha);
-}
-
-void
-fz_clip_text(fz_device *dev, fz_text *text, const fz_matrix *ctm, int accumulate)
-{
- fz_context *ctx = dev->ctx;
-
- if (dev->error_depth)
- {
- if (accumulate == 0 || accumulate == 1)
- dev->error_depth++;
- return;
- }
-
- fz_try(ctx)
- {
- if (dev->clip_text)
- dev->clip_text(dev, text, ctm, accumulate);
- }
- fz_catch(ctx)
- {
- if (accumulate == 2)
- fz_rethrow(ctx);
- dev->error_depth = 1;
- strcpy(dev->errmess, fz_caught_message(ctx));
- /* Error swallowed */
- }
-}
-
-void
-fz_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, const fz_matrix *ctm)
-{
- fz_context *ctx = dev->ctx;
-
- if (dev->error_depth)
- {
- dev->error_depth++;
- return;
- }
-
- fz_try(ctx)
- {
- if (dev->clip_stroke_text)
- dev->clip_stroke_text(dev, text, stroke, ctm);
- }
- fz_catch(ctx)
- {
- dev->error_depth = 1;
- strcpy(dev->errmess, fz_caught_message(ctx));
- /* Error swallowed */
- }
-}
-
-void
-fz_ignore_text(fz_device *dev, fz_text *text, const fz_matrix *ctm)
-{
- if (dev->error_depth)
- return;
- if (dev->ignore_text)
- dev->ignore_text(dev, text, ctm);
-}
-
-void
-fz_pop_clip(fz_device *dev)
-{
- if (dev->error_depth)
- {
- dev->error_depth--;
- if (dev->error_depth == 0)
- fz_throw(dev->ctx, FZ_ERROR_GENERIC, "%s", dev->errmess);
- return;
- }
- if (dev->pop_clip)
- dev->pop_clip(dev);
-}
-
-void
-fz_fill_shade(fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha)
-{
- if (dev->error_depth)
- return;
- if (dev->fill_shade)
- dev->fill_shade(dev, shade, ctm, alpha);
-}
-
-void
-fz_fill_image(fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha)
-{
- if (dev->error_depth)
- return;
- if (dev->fill_image)
- dev->fill_image(dev, image, ctm, alpha);
-}
-
-void
-fz_fill_image_mask(fz_device *dev, fz_image *image, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- if (dev->error_depth)
- return;
- if (dev->fill_image_mask)
- dev->fill_image_mask(dev, image, ctm, colorspace, color, alpha);
-}
-
-void
-fz_clip_image_mask(fz_device *dev, fz_image *image, const fz_rect *rect, const fz_matrix *ctm)
-{
- fz_context *ctx = dev->ctx;
-
- if (dev->error_depth)
- {
- dev->error_depth++;
- return;
- }
-
- fz_try(ctx)
- {
- if (dev->clip_image_mask)
- dev->clip_image_mask(dev, image, rect, ctm);
- }
- fz_catch(ctx)
- {
- dev->error_depth = 1;
- strcpy(dev->errmess, fz_caught_message(ctx));
- /* Error swallowed */
- }
-}
-
-void
-fz_begin_mask(fz_device *dev, const fz_rect *area, int luminosity, fz_colorspace *colorspace, float *bc)
-{
- fz_context *ctx = dev->ctx;
-
- if (dev->error_depth)
- {
- dev->error_depth++;
- return;
- }
-
- fz_try(ctx)
- {
- if (dev->begin_mask)
- dev->begin_mask(dev, area, luminosity, colorspace, bc);
- }
- fz_catch(ctx)
- {
- dev->error_depth = 1;
- strcpy(dev->errmess, fz_caught_message(ctx));
- /* Error swallowed */
- }
-}
-
-void
-fz_end_mask(fz_device *dev)
-{
- if (dev->error_depth)
- {
- /* Converts from mask to clip, so no change in stack depth */
- return;
- }
- if (dev->end_mask)
- dev->end_mask(dev);
-}
-
-void
-fz_begin_group(fz_device *dev, const fz_rect *area, int isolated, int knockout, int blendmode, float alpha)
-{
- fz_context *ctx = dev->ctx;
-
- if (dev->error_depth)
- {
- dev->error_depth++;
- return;
- }
-
- fz_try(ctx)
- {
- if (dev->begin_group)
- dev->begin_group(dev, area, isolated, knockout, blendmode, alpha);
- }
- fz_catch(ctx)
- {
- dev->error_depth = 1;
- strcpy(dev->errmess, fz_caught_message(ctx));
- /* Error swallowed */
- }
-}
-
-void
-fz_end_group(fz_device *dev)
-{
- if (dev->error_depth)
- {
- dev->error_depth--;
- if (dev->error_depth == 0)
- fz_throw(dev->ctx, FZ_ERROR_GENERIC, "%s", dev->errmess);
- return;
- }
- if (dev->end_group)
- dev->end_group(dev);
-}
-
-void
-fz_begin_tile(fz_device *dev, const fz_rect *area, const fz_rect *view, float xstep, float ystep, const fz_matrix *ctm)
-{
- (void)fz_begin_tile_id(dev, area, view, xstep, ystep, ctm, 0);
-}
-
-int
-fz_begin_tile_id(fz_device *dev, const fz_rect *area, const fz_rect *view, float xstep, float ystep, const fz_matrix *ctm, int id)
-{
- fz_context *ctx = dev->ctx;
- int ret = 0;
-
- if (dev->error_depth)
- {
- dev->error_depth++;
- return 0;
- }
-
- if (xstep < 0)
- xstep = -xstep;
- if (ystep < 0)
- ystep = -ystep;
-
- fz_try(ctx)
- {
- if (dev->begin_tile)
- ret = dev->begin_tile(dev, area, view, xstep, ystep, ctm, id);
- }
- fz_catch(ctx)
- {
- dev->error_depth = 1;
- strcpy(dev->errmess, fz_caught_message(ctx));
- /* Error swallowed */
- }
- return ret;
-}
-
-void
-fz_end_tile(fz_device *dev)
-{
- if (dev->error_depth)
- {
- dev->error_depth--;
- if (dev->error_depth == 0)
- fz_throw(dev->ctx, FZ_ERROR_GENERIC, "%s", dev->errmess);
- return;
- }
- if (dev->end_tile)
- dev->end_tile(dev);
-}
diff --git a/fitz/dev_svg.c b/fitz/dev_svg.c
deleted file mode 100644
index 4dd82120..00000000
--- a/fitz/dev_svg.c
+++ /dev/null
@@ -1,619 +0,0 @@
-#include "mupdf/fitz.h"
-
-typedef struct svg_device_s svg_device;
-
-typedef struct tile_s tile;
-
-struct tile_s
-{
- int pattern;
- fz_matrix ctm;
- fz_rect view;
- fz_rect area;
- fz_point step;
-};
-
-struct svg_device_s
-{
- fz_context *ctx;
- fz_output *out;
-
- int id;
-
- int num_tiles;
- int max_tiles;
- tile *tiles;
-};
-
-/* Helper functions */
-
-static void
-svg_dev_path(svg_device *sdev, fz_path *path)
-{
- fz_output *out = sdev->out;
- float x, y;
- int i = 0;
- fz_printf(out, " d=\"");
- while (i < path->len)
- {
- switch (path->items[i++].k)
- {
- case FZ_MOVETO:
- x = path->items[i++].v;
- y = path->items[i++].v;
- fz_printf(out, "M %g %g ", x, y);
- break;
- case FZ_LINETO:
- x = path->items[i++].v;
- y = path->items[i++].v;
- fz_printf(out, "L %g %g ", x, y);
- break;
- case FZ_CURVETO:
- x = path->items[i++].v;
- y = path->items[i++].v;
- fz_printf(out, "C %g %g ", x, y);
- x = path->items[i++].v;
- y = path->items[i++].v;
- fz_printf(out, "%g %g ", x, y);
- x = path->items[i++].v;
- y = path->items[i++].v;
- fz_printf(out, "%g %g ", x, y);
- break;
- case FZ_CLOSE_PATH:
- fz_printf(out, "Z ");
- break;
- }
- }
- fz_printf(out, "\"");
-}
-
-static void
-svg_dev_ctm(svg_device *sdev, const fz_matrix *ctm)
-{
- fz_output *out = sdev->out;
-
- if (ctm->a != 1.0 || ctm->b != 0 || ctm->c != 0 || ctm->d != 1.0 || ctm->e != 0 || ctm->f != 0)
- {
- fz_printf(out, " transform=\"matrix(%g,%g,%g,%g,%g,%g)\"",
- ctm->a, ctm->b, ctm->c, ctm->d, ctm->e, ctm->f);
- }
-}
-
-static void
-svg_dev_stroke_state(svg_device *sdev, fz_stroke_state *stroke_state)
-{
- fz_output *out = sdev->out;
-
- fz_printf(out, " stroke-width=\"%g\"", stroke_state->linewidth);
- fz_printf(out, " stroke-linecap=\"%s\"",
- (stroke_state->start_cap == FZ_LINECAP_SQUARE ? "square" :
- (stroke_state->start_cap == FZ_LINECAP_ROUND ? "round" : "butt")));
- if (stroke_state->dash_len != 0)
- {
- int i;
- fz_printf(out, " stroke-dasharray=");
- for (i = 0; i < stroke_state->dash_len; i++)
- fz_printf(out, "%c%g", (i == 0 ? '\"' : ','), stroke_state->dash_list[i]);
- fz_printf(out, "\"");
- if (stroke_state->dash_phase != 0)
- fz_printf(out, " stroke-dashoffset=\"%g\"", stroke_state->dash_phase);
- }
- if (stroke_state->linejoin == FZ_LINEJOIN_MITER || stroke_state->linejoin == FZ_LINEJOIN_MITER_XPS)
- fz_printf(out, " stroke-miterlimit=\"%g\"", stroke_state->miterlimit);
- fz_printf(out, " stroke-linejoin=\"%s\"",
- (stroke_state->linejoin == FZ_LINEJOIN_BEVEL ? "bevel" :
- (stroke_state->linejoin == FZ_LINEJOIN_ROUND ? "round" : "miter")));
-}
-
-static void
-svg_dev_fill_color(svg_device *sdev, fz_colorspace *colorspace, float *color, float alpha)
-{
- fz_context *ctx = sdev->ctx;
- fz_output *out = sdev->out;
- float rgb[FZ_MAX_COLORS];
-
- if (colorspace != fz_device_rgb(ctx))
- {
- /* If it's not rgb, make it rgb */
- colorspace->to_rgb(ctx, colorspace, color, rgb);
- color = rgb;
- }
-
- if (color[0] == 0 && color[1] == 0 && color[2] == 0)
- {
- /* don't send a fill, as it will be assumed to be black */
- }
- else
- fz_printf(out, " fill=\"rgb(%d,%d,%d)\"", (int)(255*color[0] + 0.5), (int)(255*color[1] + 0.5), (int)(255*color[2]+0.5));
- if (alpha != 1)
- fz_printf(out, " fill-opacity=\"%g\"", alpha);
-}
-
-static void
-svg_dev_stroke_color(svg_device *sdev, fz_colorspace *colorspace, float *color, float alpha)
-{
- fz_context *ctx = sdev->ctx;
- fz_output *out = sdev->out;
- float rgb[FZ_MAX_COLORS];
-
- if (colorspace != fz_device_rgb(ctx))
- {
- /* If it's not rgb, make it rgb */
- colorspace->to_rgb(ctx, colorspace, color, rgb);
- color = rgb;
- }
-
- fz_printf(out, " fill=\"none\" stroke=\"rgb(%d,%d,%d)\"", (int)(255*color[0] + 0.5), (int)(255*color[1] + 0.5), (int)(255*color[2]+0.5));
- if (alpha != 1)
- fz_printf(out, " stroke-opacity=\"%g\"", alpha);
-}
-
-static void
-svg_dev_text(svg_device *sdev, const fz_matrix *ctm, fz_text *text)
-{
- fz_output *out = sdev->out;
- int i;
- fz_matrix inverse;
- fz_matrix local_trm;
- float size;
-
- /* Rely on the fact that trm.{e,f} == 0 */
- size = fz_matrix_expansion(&text->trm);
- local_trm.a = text->trm.a / size;
- local_trm.b = text->trm.b / size;
- local_trm.c = -text->trm.c / size;
- local_trm.d = -text->trm.d / size;
- local_trm.e = 0;
- local_trm.f = 0;
- fz_invert_matrix(&inverse, &local_trm);
- fz_concat(&local_trm, &local_trm, ctm);
-
- fz_printf(out, " transform=\"matrix(%g,%g,%g,%g,%g,%g)\"",
- local_trm.a, local_trm.b, local_trm.c, local_trm.d, local_trm.e, local_trm.f);
- fz_printf(out, " font-size=\"%g\"", size);
- fz_printf(out, " font-family=\"%s\"", text->font->name);
-
- fz_printf(out, " x=");
- for (i=0; i < text->len; i++)
- {
- fz_text_item *it = &text->items[i];
- fz_point p;
- p.x = it->x;
- p.y = it->y;
- fz_transform_point(&p, &inverse);
- fz_printf(out, "%c%g", i == 0 ? '\"' : ' ', p.x);
- }
- fz_printf(out, "\" y=");
- for (i=0; i < text->len; i++)
- {
- fz_text_item *it = &text->items[i];
- fz_point p;
- p.x = it->x;
- p.y = it->y;
- fz_transform_point(&p, &inverse);
- fz_printf(out, "%c%g", i == 0 ? '\"' : ' ', p.y);
- }
- fz_printf(out, "\">\n");
- for (i=0; i < text->len; i++)
- {
- fz_text_item *it = &text->items[i];
- int c = it->ucs;
- if (c >= 32 && c <= 127 && c != '<' && c != '&')
- fz_printf(out, "%c", c);
- else
- fz_printf(out, "&#x%04x;", c);
- }
- fz_printf(out, "\n</text>\n");
-}
-
-/* Entry points */
-
-static void
-svg_dev_fill_path(fz_device *dev, fz_path *path, int even_odd, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- svg_device *sdev = dev->user;
- fz_output *out = sdev->out;
-
- fz_printf(out, "<path");
- svg_dev_ctm(sdev, ctm);
- svg_dev_path(sdev, path);
- svg_dev_fill_color(sdev, colorspace, color, alpha);
- if (even_odd)
- fz_printf(out, " fill-rule=\"evenodd\" ");
- fz_printf(out, "/>\n");
-}
-
-static void
-svg_dev_stroke_path(fz_device *dev, fz_path *path, fz_stroke_state *stroke, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- svg_device *sdev = dev->user;
- fz_output *out = sdev->out;
-
- fz_printf(out, "<path");
- svg_dev_ctm(sdev, ctm);
- svg_dev_stroke_state(sdev, stroke);
- svg_dev_stroke_color(sdev, colorspace, color, alpha);
- svg_dev_path(sdev, path);
- fz_printf(out, "/>\n");
-}
-
-static void
-svg_dev_clip_path(fz_device *dev, fz_path *path, const fz_rect *rect, int even_odd, const fz_matrix *ctm)
-{
- svg_device *sdev = dev->user;
- fz_output *out = sdev->out;
- int num = sdev->id++;
-
- fz_printf(out, "<clipPath id=\"cp%d\">\n", num);
- fz_printf(out, "<path");
- svg_dev_ctm(sdev, ctm);
- svg_dev_path(sdev, path);
- if (even_odd)
- fz_printf(out, " fill-rule=\"evenodd\" ");
- fz_printf(out, "/>\n</clipPath>\n<g clip-path=\"url(#cp%d)\">\n", num);
-}
-
-static void
-svg_dev_clip_stroke_path(fz_device *dev, fz_path *path, const fz_rect *rect, fz_stroke_state *stroke, const fz_matrix *ctm)
-{
- svg_device *sdev = dev->user;
- fz_output *out = sdev->out;
- fz_context *ctx = dev->ctx;
- fz_rect bounds;
- int num = sdev->id++;
- float white[3] = { 255, 255, 255 };
-
- fz_bound_path(ctx, path, stroke, ctm, &bounds);
-
- fz_printf(out, "<mask id=\"ma%d\" x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" maskUnits=\"userSpaceOnUse\" maskContentUnits=\"userSpaceOnUse\" >\n",
- num, bounds.x0, bounds.y0, bounds.x1 - bounds.x0, bounds.y1 - bounds.y0);
- fz_printf(out, "<path");
- svg_dev_ctm(sdev, ctm);
- svg_dev_stroke_state(sdev, stroke);
- svg_dev_stroke_color(sdev, fz_device_rgb(ctx), white, 1);
- svg_dev_path(sdev, path);
- fz_printf(out, "/>\n</mask>\n<g mask=\"url(#ma%d)\">\n", num);
-}
-
-static void
-svg_dev_fill_text(fz_device *dev, fz_text *text, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- svg_device *sdev = dev->user;
- fz_output *out = sdev->out;
-
- fz_printf(out, "<text");
- svg_dev_fill_color(sdev, colorspace, color, alpha);
- svg_dev_text(sdev, ctm, text);
-}
-
-static void
-svg_dev_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- svg_device *sdev = dev->user;
- fz_output *out = sdev->out;
-
- fz_printf(out, "<text");
- svg_dev_ctm(sdev, ctm);
- svg_dev_stroke_state(sdev, stroke);
- svg_dev_stroke_color(sdev, colorspace, color, alpha);
- svg_dev_text(sdev, ctm, text);
-}
-
-static void
-svg_dev_clip_text(fz_device *dev, fz_text *text, const fz_matrix *ctm, int accumulate)
-{
- svg_device *sdev = dev->user;
- fz_output *out = sdev->out;
- fz_context *ctx = dev->ctx;
- fz_rect bounds;
- int num = sdev->id++;
- float white[3] = { 255, 255, 255 };
-
- fz_bound_text(ctx, text, NULL, ctm, &bounds);
-
- fz_printf(out, "<mask id=\"ma%d\" x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" maskUnits=\"userSpaceOnUse\" maskContentUnits=\"userSpaceOnUse\" >\n",
- num, bounds.x0, bounds.y0, bounds.x1 - bounds.x0, bounds.y1 - bounds.y0);
- fz_printf(out, "<text");
- svg_dev_fill_color(sdev, fz_device_rgb(ctx), white, 1.0f);
- svg_dev_text(sdev, ctm, text);
- fz_printf(out, "</mask>\n<g mask=\"url(#ma%d)\">\n", num);
-}
-
-static void
-svg_dev_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, const fz_matrix *ctm)
-{
- svg_device *sdev = dev->user;
- fz_output *out = sdev->out;
- fz_context *ctx = dev->ctx;
- fz_rect bounds;
- int num = sdev->id++;
- float white[3] = { 255, 255, 255 };
-
- fz_bound_text(ctx, text, NULL, ctm, &bounds);
-
- fz_printf(out, "<mask id=\"ma%d\" x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" maskUnits=\"userSpaceOnUse\" maskContentUnits=\"userSpaceOnUse\" >\n",
- num, bounds.x0, bounds.y0, bounds.x1 - bounds.x0, bounds.y1 - bounds.y0);
- fz_printf(out, "<text");
- svg_dev_stroke_state(sdev, stroke);
- svg_dev_stroke_color(sdev, fz_device_rgb(ctx), white, 1.0f);
- svg_dev_text(sdev, ctm, text);
- fz_printf(out, "</mask>\n<g mask=\"url(#ma%d)\">\n", num);
-}
-
-static void
-svg_dev_ignore_text(fz_device *dev, fz_text *text, const fz_matrix *ctm)
-{
-}
-
-static void
-send_data_base64(fz_output *out, fz_buffer *buffer)
-{
- int i, len;
- static const char set[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
- len = buffer->len/3;
- for (i = 0; i < len; i++)
- {
- int c = buffer->data[3*i];
- int d = buffer->data[3*i+1];
- int e = buffer->data[3*i+2];
- if ((i & 15) == 0)
- fz_printf(out, "\n");
- fz_printf(out, "%c%c%c%c", set[c>>2], set[((c&3)<<4)|(d>>4)], set[((d&15)<<2)|(e>>6)], set[e & 63]);
- }
- i *= 3;
- switch (buffer->len-i)
- {
- case 2:
- {
- int c = buffer->data[i];
- int d = buffer->data[i+1];
- fz_printf(out, "%c%c%c=", set[c>>2], set[((c&3)<<4)|(d>>4)], set[((d&15)<<2)]);
- break;
- }
- case 1:
- {
- int c = buffer->data[i];
- fz_printf(out, "%c%c==", set[c>>2], set[(c&3)<<4]);
- break;
- }
- default:
- case 0:
- break;
- }
-}
-
-static void
-svg_dev_fill_image(fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha)
-{
- svg_device *sdev = (svg_device *)dev->user;
- fz_context *ctx = dev->ctx;
- fz_output *out = sdev->out;
- fz_matrix local_ctm = *ctm;
- fz_matrix scale = { 1.0f/image->w, 0, 0, 1.0f/image->h, 0, 0};
-
- fz_concat(&local_ctm, &scale, ctm);
- fz_printf(out, "<image");
- svg_dev_ctm(sdev, &local_ctm);
- fz_printf(out, "width=\"%dpx\" height=\"%dpx\" xlink:href=\"data:", image->w, image->h);
- switch (image->buffer == NULL ? FZ_IMAGE_JPX : image->buffer->params.type)
- {
- case FZ_IMAGE_JPEG:
- fz_printf(out, "image/jpeg;base64,");
- send_data_base64(out, image->buffer->buffer);
- break;
- case FZ_IMAGE_PNG:
- fz_printf(out, "image/png;base64,");
- send_data_base64(out, image->buffer->buffer);
- break;
- default:
- {
- fz_buffer *buf = fz_image_as_png(ctx, image, image->w, image->h);
- fz_printf(out, "image/png;base64,");
- send_data_base64(out, buf);
- fz_drop_buffer(ctx, buf);
- break;
- }
- }
- fz_printf(out, "\"/>\n");
-}
-
-static void
-svg_dev_fill_shade(fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha)
-{
-}
-
-static void
-svg_dev_fill_image_mask(fz_device *dev, fz_image *image, const fz_matrix *ctm,
-fz_colorspace *colorspace, float *color, float alpha)
-{
-}
-
-static void
-svg_dev_clip_image_mask(fz_device *dev, fz_image *image, const fz_rect *rect, const fz_matrix *ctm)
-{
- svg_device *sdev = dev->user;
- fz_output *out = sdev->out;
-
- fz_printf(out, "<g>\n");
-}
-
-static void
-svg_dev_pop_clip(fz_device *dev)
-{
- svg_device *sdev = (svg_device *)dev->user;
- fz_output *out = sdev->out;
-
- /* FIXME */
- fz_printf(out, "</g>\n");
-}
-
-static void
-svg_dev_begin_mask(fz_device *dev, const fz_rect *bbox, int luminosity, fz_colorspace *colorspace, float *color)
-{
-}
-
-static void
-svg_dev_end_mask(fz_device *dev)
-{
-
-}
-
-static void
-svg_dev_begin_group(fz_device *dev, const fz_rect *bbox, int isolated, int knockout, int blendmode, float alpha)
-{
-
-}
-
-static void
-svg_dev_end_group(fz_device *dev)
-{
-
-}
-
-static int
-svg_dev_begin_tile(fz_device *dev, const fz_rect *area, const fz_rect *view, float xstep, float ystep, const fz_matrix *ctm, int id)
-{
- svg_device *sdev = (svg_device *)dev->user;
- fz_output *out = sdev->out;
- fz_context *ctx = dev->ctx;
- fz_matrix inverse;
- int num;
- tile *t;
-
- if (sdev->num_tiles == sdev->max_tiles)
- {
- int n = (sdev->num_tiles == 0 ? 4 : sdev->num_tiles * 2);
-
- sdev->tiles = fz_resize_array(ctx, sdev->tiles, n, sizeof(tile));
- sdev->max_tiles = n;
- }
- num = sdev->num_tiles++;
- t = &sdev->tiles[num];
- t->area = *area;
- t->view = *view;
- t->ctm = *ctm;
- t->pattern = sdev->id++;
- t->step.x = xstep;
- t->step.y = ystep;
-
- /* view = area of our reference tile in pattern space.
- * area = area to tile into in pattern space.
- * xstep/ystep = pattern repeat step in pattern space.
- * All of these need to be transformed by ctm to get to device space.
- * SVG only allows us to specify pattern tiles as axis aligned
- * rectangles, so we send these through as is, and ensure that the
- * correct matrix is used on the fill.
- */
-
- /* In svg, the reference tile is taken from (x,y) to (x+width,y+height)
- * and is repeated at (x+n*width,y+m*height) for all integer n and m.
- * This means that width and height correspond to xstep and ystep. */
- fz_printf(out, "<pattern id=\"pa%d\" patternUnits=\"userSpaceOnUse\" patternContentUnits=\"userSpaceOnUse\"",
- t->pattern);
- fz_printf(out, " x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\">\n",
- view->x0, view->y0, xstep, ystep);
- /* All the pattern contents will have their own ctm applied. Let's
- * undo the current one to allow for this */
- fz_invert_matrix(&inverse, ctm);
- fz_printf(out, "<g");
- svg_dev_ctm(sdev, &inverse);
- fz_printf(out, ">\n");
-
- return 0;
-}
-
-static void
-svg_dev_end_tile(fz_device *dev)
-{
- svg_device *sdev = (svg_device *)dev->user;
- fz_output *out = sdev->out;
- int num;
- tile *t;
-
- if (sdev->num_tiles == 0)
- return;
- num = --sdev->num_tiles;
- t = &sdev->tiles[num];
-
- fz_printf(out, "</g>\n</pattern>\n");
- fz_printf(out, "<rect");
- svg_dev_ctm(sdev, &t->ctm);
- fz_printf(out, " fill=\"url(#pa%d)\" x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\"/>\n",
- t->pattern, t->area.x0, t->area.y0, t->area.x1 - t->area.x0, t->area.y1 - t->area.y0);
-}
-
-static void
-svg_dev_free_user(fz_device *dev)
-{
- svg_device *sdev = dev->user;
- fz_context *ctx = sdev->ctx;
- fz_output *out = sdev->out;
-
- fz_free(ctx, sdev->tiles);
-
- fz_printf(out, "</svg>\n");
-
- fz_free(ctx, sdev);
-}
-
-fz_device *fz_new_svg_device(fz_context *ctx, fz_output *out, float page_width, float page_height)
-{
- svg_device *sdev = fz_malloc_struct(ctx, svg_device);
- fz_device *dev;
-
- fz_try(ctx)
- {
- sdev->ctx = ctx;
- sdev->out = out;
- sdev->id = 0;
-
- dev = fz_new_device(ctx, sdev);
- }
- fz_catch(ctx)
- {
- fz_free(ctx, sdev);
- fz_rethrow(ctx);
- }
-
- dev->free_user = svg_dev_free_user;
-
- dev->fill_path = svg_dev_fill_path;
- dev->stroke_path = svg_dev_stroke_path;
- dev->clip_path = svg_dev_clip_path;
- dev->clip_stroke_path = svg_dev_clip_stroke_path;
-
- dev->fill_text = svg_dev_fill_text;
- dev->stroke_text = svg_dev_stroke_text;
- dev->clip_text = svg_dev_clip_text;
- dev->clip_stroke_text = svg_dev_clip_stroke_text;
- dev->ignore_text = svg_dev_ignore_text;
-
- dev->fill_shade = svg_dev_fill_shade;
- dev->fill_image = svg_dev_fill_image;
- dev->fill_image_mask = svg_dev_fill_image_mask;
- dev->clip_image_mask = svg_dev_clip_image_mask;
-
- dev->pop_clip = svg_dev_pop_clip;
-
- dev->begin_mask = svg_dev_begin_mask;
- dev->end_mask = svg_dev_end_mask;
- dev->begin_group = svg_dev_begin_group;
- dev->end_group = svg_dev_end_group;
-
- dev->begin_tile = svg_dev_begin_tile;
- dev->end_tile = svg_dev_end_tile;
-
- fz_printf(out, "<?xml version=\"1.0\" standalone=\"no\"?>\n");
- fz_printf(out, "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
- fz_printf(out, "<svg xmlns=\"http://www.w3.org/2000/svg\" "
- "xmlns:xlink=\"http://www.w3.org/1999/xlink\" version=\"1.1\" "
- "width=\"%gcm\" height=\"%gcm\" viewBox=\"0 0 %g %g\">\n",
- page_width*2.54/72, page_height*2.54/72, page_width, page_height);
-
- return dev;
-}
diff --git a/fitz/dev_trace.c b/fitz/dev_trace.c
deleted file mode 100644
index b3cade91..00000000
--- a/fitz/dev_trace.c
+++ /dev/null
@@ -1,339 +0,0 @@
-#include "mupdf/fitz.h"
-
-static void
-fz_trace_matrix(const fz_matrix *ctm)
-{
- printf(" matrix=\"%g %g %g %g %g %g\"",
- ctm->a, ctm->b, ctm->c, ctm->d, ctm->e, ctm->f);
-}
-
-static void
-fz_trace_trm(const fz_matrix *trm)
-{
- printf(" trm=\"%g %g %g %g\"",
- trm->a, trm->b, trm->c, trm->d);
-}
-
-static void
-fz_trace_color(fz_colorspace *colorspace, float *color, float alpha)
-{
- int i;
- printf(" colorspace=\"%s\" color=\"", colorspace->name);
- for (i = 0; i < colorspace->n; i++)
- printf("%s%g", i == 0 ? "" : " ", color[i]);
- printf("\"");
- if (alpha < 1)
- printf(" alpha=\"%g\"", alpha);
-}
-
-static void
-fz_trace_path(fz_path *path, int indent)
-{
- float x, y;
- int i = 0;
- int n;
- while (i < path->len)
- {
- for (n = 0; n < indent; n++)
- putchar(' ');
- switch (path->items[i++].k)
- {
- case FZ_MOVETO:
- x = path->items[i++].v;
- y = path->items[i++].v;
- printf("<moveto x=\"%g\" y=\"%g\"/>\n", x, y);
- break;
- case FZ_LINETO:
- x = path->items[i++].v;
- y = path->items[i++].v;
- printf("<lineto x=\"%g\" y=\"%g\"/>\n", x, y);
- break;
- case FZ_CURVETO:
- x = path->items[i++].v;
- y = path->items[i++].v;
- printf("<curveto x1=\"%g\" y1=\"%g\"", x, y);
- x = path->items[i++].v;
- y = path->items[i++].v;
- printf(" x2=\"%g\" y2=\"%g\"", x, y);
- x = path->items[i++].v;
- y = path->items[i++].v;
- printf(" x3=\"%g\" y3=\"%g\"/>\n", x, y);
- break;
- case FZ_CLOSE_PATH:
- printf("<closepath/>\n");
- break;
- }
- }
-}
-
-static void
-fz_trace_begin_page(fz_device *dev, const fz_rect *rect, const fz_matrix *ctm)
-{
- printf("<page mediabox=\"%g %g %g %g\"", rect->x0, rect->y0, rect->x1, rect->y1);
- fz_trace_matrix(ctm);
- printf(">\n");
-}
-
-static void
-fz_trace_end_page(fz_device *dev)
-{
- printf("</page>\n");
-}
-
-static void
-fz_trace_fill_path(fz_device *dev, fz_path *path, int even_odd, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- printf("<fill_path");
- if (even_odd)
- printf(" winding=\"eofill\"");
- else
- printf(" winding=\"nonzero\"");
- fz_trace_color(colorspace, color, alpha);
- fz_trace_matrix(ctm);
- printf(">\n");
- fz_trace_path(path, 0);
- printf("</fill_path>\n");
-}
-
-static void
-fz_trace_stroke_path(fz_device *dev, fz_path *path, fz_stroke_state *stroke, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- int i;
-
- printf("<stroke_path");
- printf(" linewidth=\"%g\"", stroke->linewidth);
- printf(" miterlimit=\"%g\"", stroke->miterlimit);
- printf(" linecap=\"%d,%d,%d\"", stroke->start_cap, stroke->dash_cap, stroke->end_cap);
- printf(" linejoin=\"%d\"", stroke->linejoin);
-
- if (stroke->dash_len)
- {
- printf(" dash_phase=\"%g\" dash=\"", stroke->dash_phase);
- for (i = 0; i < stroke->dash_len; i++)
- printf("%s%g", i > 0 ? " " : "", stroke->dash_list[i]);
- printf("\"");
- }
-
- fz_trace_color(colorspace, color, alpha);
- fz_trace_matrix(ctm);
- printf(">\n");
-
- fz_trace_path(path, 0);
-
- printf("</stroke_path>\n");
-}
-
-static void
-fz_trace_clip_path(fz_device *dev, fz_path *path, const fz_rect *rect, int even_odd, const fz_matrix *ctm)
-{
- printf("<clip_path");
- if (even_odd)
- printf(" winding=\"eofill\"");
- else
- printf(" winding=\"nonzero\"");
- fz_trace_matrix(ctm);
- if (rect)
- printf(" contentbbox=\"%g %g %g %g\">\n", rect->x0, rect->y0, rect->x1, rect->y1);
- else
- printf(">\n");
- fz_trace_path(path, 0);
- printf("</clip_path>\n");
-}
-
-static void
-fz_trace_clip_stroke_path(fz_device *dev, fz_path *path, const fz_rect *rect, fz_stroke_state *stroke, const fz_matrix *ctm)
-{
- printf("<clip_stroke_path");
- fz_trace_matrix(ctm);
- printf(">\n");
- fz_trace_path(path, 0);
- printf("</clip_stroke_path>\n");
-}
-
-static void
-fz_trace_fill_text(fz_device *dev, fz_text *text, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- printf("<fill_text font=\"%s\" wmode=\"%d\"", text->font->name, text->wmode);
- fz_trace_color(colorspace, color, alpha);
- fz_trace_matrix(ctm);
- fz_trace_trm(&text->trm);
- printf(">\n");
- fz_print_text(dev->ctx, stdout, text);
- printf("</fill_text>\n");
-}
-
-static void
-fz_trace_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- printf("<stroke_text font=\"%s\" wmode=\"%d\"", text->font->name, text->wmode);
- fz_trace_color(colorspace, color, alpha);
- fz_trace_matrix(ctm);
- fz_trace_trm(&text->trm);
- printf(">\n");
- fz_print_text(dev->ctx, stdout, text);
- printf("</stroke_text>\n");
-}
-
-static void
-fz_trace_clip_text(fz_device *dev, fz_text *text, const fz_matrix *ctm, int accumulate)
-{
- printf("<clip_text font=\"%s\" wmode=\"%d\"", text->font->name, text->wmode);
- printf(" accumulate=\"%d\"", accumulate);
- fz_trace_matrix(ctm);
- fz_trace_trm(&text->trm);
- printf(">\n");
- fz_print_text(dev->ctx, stdout, text);
- printf("</clip_text>\n");
-}
-
-static void
-fz_trace_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, const fz_matrix *ctm)
-{
- printf("<clip_stroke_text font=\"%s\" wmode=\"%d\"", text->font->name, text->wmode);
- fz_trace_matrix(ctm);
- fz_trace_trm(&text->trm);
- printf(">\n");
- fz_print_text(dev->ctx, stdout, text);
- printf("</clip_stroke_text>\n");
-}
-
-static void
-fz_trace_ignore_text(fz_device *dev, fz_text *text, const fz_matrix *ctm)
-{
- printf("<ignore_text font=\"%s\" wmode=\"%d\"", text->font->name, text->wmode);
- fz_trace_matrix(ctm);
- fz_trace_trm(&text->trm);
- printf(">\n");
- fz_print_text(dev->ctx, stdout, text);
- printf("</ignore_text>\n");
-}
-
-static void
-fz_trace_fill_image(fz_device *dev, fz_image *image, const fz_matrix *ctm, float alpha)
-{
- printf("<fill_image alpha=\"%g\"", alpha);
- fz_trace_matrix(ctm);
- printf(" width=\"%d\" height=\"%d\"", image->w, image->h);
- printf("/>\n");
-}
-
-static void
-fz_trace_fill_shade(fz_device *dev, fz_shade *shade, const fz_matrix *ctm, float alpha)
-{
- printf("<fill_shade alpha=\"%g\"", alpha);
- fz_trace_matrix(ctm);
- printf("/>\n");
-}
-
-static void
-fz_trace_fill_image_mask(fz_device *dev, fz_image *image, const fz_matrix *ctm,
-fz_colorspace *colorspace, float *color, float alpha)
-{
- printf("<fill_image_mask");
- fz_trace_matrix(ctm);
- fz_trace_color(colorspace, color, alpha);
- printf(" width=\"%d\" height=\"%d\"", image->w, image->h);
- printf("/>\n");
-}
-
-static void
-fz_trace_clip_image_mask(fz_device *dev, fz_image *image, const fz_rect *rect, const fz_matrix *ctm)
-{
- printf("<clip_image_mask");
- fz_trace_matrix(ctm);
- printf(" width=\"%d\" height=\"%d\"", image->w, image->h);
- printf("/>\n");
-}
-
-static void
-fz_trace_pop_clip(fz_device *dev)
-{
- printf("<pop_clip/>\n");
-}
-
-static void
-fz_trace_begin_mask(fz_device *dev, const fz_rect *bbox, int luminosity, fz_colorspace *colorspace, float *color)
-{
- printf("<mask bbox=\"%g %g %g %g\" s=\"%s\"",
- bbox->x0, bbox->y0, bbox->x1, bbox->y1,
- luminosity ? "luminosity" : "alpha");
- printf(">\n");
-}
-
-static void
-fz_trace_end_mask(fz_device *dev)
-{
- printf("</mask>\n");
-}
-
-static void
-fz_trace_begin_group(fz_device *dev, const fz_rect *bbox, int isolated, int knockout, int blendmode, float alpha)
-{
- printf("<group bbox=\"%g %g %g %g\" isolated=\"%d\" knockout=\"%d\" blendmode=\"%s\" alpha=\"%g\">\n",
- bbox->x0, bbox->y0, bbox->x1, bbox->y1,
- isolated, knockout, fz_blendmode_name(blendmode), alpha);
-}
-
-static void
-fz_trace_end_group(fz_device *dev)
-{
- printf("</group>\n");
-}
-
-static int
-fz_trace_begin_tile(fz_device *dev, const fz_rect *area, const fz_rect *view, float xstep, float ystep, const fz_matrix *ctm, int id)
-{
- printf("<tile");
- printf(" area=\"%g %g %g %g\"", area->x0, area->y0, area->x1, area->y1);
- printf(" view=\"%g %g %g %g\"", view->x0, view->y0, view->x1, view->y1);
- printf(" xstep=\"%g\" ystep=\"%g\"", xstep, ystep);
- fz_trace_matrix(ctm);
- printf(">\n");
- return 0;
-}
-
-static void
-fz_trace_end_tile(fz_device *dev)
-{
- printf("</tile>\n");
-}
-
-fz_device *fz_new_trace_device(fz_context *ctx)
-{
- fz_device *dev = fz_new_device(ctx, NULL);
-
- dev->begin_page = fz_trace_begin_page;
- dev->end_page = fz_trace_end_page;
-
- dev->fill_path = fz_trace_fill_path;
- dev->stroke_path = fz_trace_stroke_path;
- dev->clip_path = fz_trace_clip_path;
- dev->clip_stroke_path = fz_trace_clip_stroke_path;
-
- dev->fill_text = fz_trace_fill_text;
- dev->stroke_text = fz_trace_stroke_text;
- dev->clip_text = fz_trace_clip_text;
- dev->clip_stroke_text = fz_trace_clip_stroke_text;
- dev->ignore_text = fz_trace_ignore_text;
-
- dev->fill_shade = fz_trace_fill_shade;
- dev->fill_image = fz_trace_fill_image;
- dev->fill_image_mask = fz_trace_fill_image_mask;
- dev->clip_image_mask = fz_trace_clip_image_mask;
-
- dev->pop_clip = fz_trace_pop_clip;
-
- dev->begin_mask = fz_trace_begin_mask;
- dev->end_mask = fz_trace_end_mask;
- dev->begin_group = fz_trace_begin_group;
- dev->end_group = fz_trace_end_group;
-
- dev->begin_tile = fz_trace_begin_tile;
- dev->end_tile = fz_trace_end_tile;
-
- return dev;
-}
diff --git a/fitz/doc_document.c b/fitz/doc_document.c
deleted file mode 100644
index 8adbf816..00000000
--- a/fitz/doc_document.c
+++ /dev/null
@@ -1,274 +0,0 @@
-#include "mupdf/fitz.h"
-
-/* Yuck! Promiscuous we are. */
-extern struct pdf_document *pdf_open_document(fz_context *ctx, const char *filename);
-extern struct xps_document *xps_open_document(fz_context *ctx, const char *filename);
-extern struct cbz_document *cbz_open_document(fz_context *ctx, const char *filename);
-extern struct image_document *image_open_document(fz_context *ctx, const char *filename);
-
-extern struct pdf_document *pdf_open_document_with_stream(fz_context *ctx, fz_stream *file);
-extern struct xps_document *xps_open_document_with_stream(fz_context *ctx, fz_stream *file);
-extern struct cbz_document *cbz_open_document_with_stream(fz_context *ctx, fz_stream *file);
-extern struct image_document *image_open_document_with_stream(fz_context *ctx, fz_stream *file);
-
-extern int pdf_js_supported(void);
-
-static inline int fz_tolower(int c)
-{
- if (c >= 'A' && c <= 'Z')
- return c + 32;
- return c;
-}
-
-static inline int fz_strcasecmp(const char *a, const char *b)
-{
- while (fz_tolower(*a) == fz_tolower(*b))
- {
- if (*a++ == 0)
- return 0;
- b++;
- }
- return fz_tolower(*a) - fz_tolower(*b);
-}
-
-fz_document *
-fz_open_document_with_stream(fz_context *ctx, const char *magic, fz_stream *stream)
-{
- char *ext = strrchr(magic, '.');
-
- if (ext)
- {
- if (!fz_strcasecmp(ext, ".xps") || !fz_strcasecmp(ext, ".rels") || !fz_strcasecmp(ext, ".oxps"))
- return (fz_document*) xps_open_document_with_stream(ctx, stream);
- if (!fz_strcasecmp(ext, ".cbz") || !fz_strcasecmp(ext, ".zip"))
- return (fz_document*) cbz_open_document_with_stream(ctx, stream);
- if (!fz_strcasecmp(ext, ".pdf"))
- return (fz_document*) pdf_open_document_with_stream(ctx, stream);
- if (!fz_strcasecmp(ext, ".png") || !fz_strcasecmp(ext, ".jpg") ||
- !fz_strcasecmp(ext, ".jpeg") || !fz_strcasecmp(ext, ".jfif") ||
- !fz_strcasecmp(ext, ".jfif-tbnl") || !fz_strcasecmp(ext, ".jpe") ||
- !fz_strcasecmp(ext, ".tif") || !fz_strcasecmp(ext, ".tiff"))
- return (fz_document*) image_open_document_with_stream(ctx, stream);
- }
-
- if (!strcmp(magic, "cbz") || !strcmp(magic, "application/x-cbz"))
- return (fz_document*) cbz_open_document_with_stream(ctx, stream);
- if (!strcmp(magic, "xps") || !strcmp(magic, "oxps") || !strcmp(magic, "application/vnd.ms-xpsdocument"))
- return (fz_document*) xps_open_document_with_stream(ctx, stream);
- if (!strcmp(magic, "pdf") || !strcmp(magic, "application/pdf"))
- return (fz_document*) pdf_open_document_with_stream(ctx, stream);
- if (!strcmp(magic, "png") || !strcmp(magic, "image/png") ||
- !strcmp(magic, "jpg") || !strcmp(magic, "image/jpeg") ||
- !strcmp(magic, "jpeg") || !strcmp(magic, "image/pjpeg") ||
- !strcmp(magic, "jpe") || !strcmp(magic, "jfif") ||
- !strcmp(magic, "tif") || !strcmp(magic, "image/tiff") ||
- !strcmp(magic, "tiff") || !strcmp(magic, "image/x-tiff"))
- return (fz_document*) image_open_document_with_stream(ctx, stream);
-
- /* last guess: pdf */
- return (fz_document*) pdf_open_document_with_stream(ctx, stream);
-}
-
-fz_document *
-fz_open_document(fz_context *ctx, const char *filename)
-{
- char *ext = strrchr(filename, '.');
-
- if (ext)
- {
- if (!fz_strcasecmp(ext, ".xps") || !fz_strcasecmp(ext, ".rels") || !fz_strcasecmp(ext, ".oxps"))
- return (fz_document*) xps_open_document(ctx, filename);
- if (!fz_strcasecmp(ext, ".cbz") || !fz_strcasecmp(ext, ".zip"))
- return (fz_document*) cbz_open_document(ctx, filename);
- if (!fz_strcasecmp(ext, ".pdf"))
- return (fz_document*) pdf_open_document(ctx, filename);
- if (!fz_strcasecmp(ext, ".png") || !fz_strcasecmp(ext, ".jpg") ||
- !fz_strcasecmp(ext, ".jpeg") || !fz_strcasecmp(ext, ".jpe") ||
- !fz_strcasecmp(ext, ".jfif") || !fz_strcasecmp(ext, ".jfif-tbnl") ||
- !fz_strcasecmp(ext, ".tif") || !fz_strcasecmp(ext, ".tiff"))
- return (fz_document*) image_open_document(ctx, filename);
- }
-
- /* last guess: pdf */
- return (fz_document*) pdf_open_document(ctx, filename);
-}
-
-void
-fz_close_document(fz_document *doc)
-{
- if (doc && doc->close)
- doc->close(doc);
-}
-
-int
-fz_needs_password(fz_document *doc)
-{
- if (doc && doc->needs_password)
- return doc->needs_password(doc);
- return 0;
-}
-
-int
-fz_authenticate_password(fz_document *doc, char *password)
-{
- if (doc && doc->authenticate_password)
- return doc->authenticate_password(doc, password);
- return 1;
-}
-
-fz_outline *
-fz_load_outline(fz_document *doc)
-{
- if (doc && doc->load_outline)
- return doc->load_outline(doc);
- return NULL;
-}
-
-int
-fz_count_pages(fz_document *doc)
-{
- if (doc && doc->count_pages)
- return doc->count_pages(doc);
- return 0;
-}
-
-fz_page *
-fz_load_page(fz_document *doc, int number)
-{
- if (doc && doc->load_page)
- return doc->load_page(doc, number);
- return NULL;
-}
-
-fz_link *
-fz_load_links(fz_document *doc, fz_page *page)
-{
- if (doc && doc->load_links && page)
- return doc->load_links(doc, page);
- return NULL;
-}
-
-fz_rect *
-fz_bound_page(fz_document *doc, fz_page *page, fz_rect *r)
-{
- if (doc && doc->bound_page && page && r)
- return doc->bound_page(doc, page, r);
- if (r)
- *r = fz_empty_rect;
- return r;
-}
-
-fz_annot *
-fz_first_annot(fz_document *doc, fz_page *page)
-{
- if (doc && doc->first_annot && page)
- return doc->first_annot(doc, page);
- return NULL;
-}
-
-fz_annot *
-fz_next_annot(fz_document *doc, fz_annot *annot)
-{
- if (doc && doc->next_annot && annot)
- return doc->next_annot(doc, annot);
- return NULL;
-}
-
-fz_rect *
-fz_bound_annot(fz_document *doc, fz_annot *annot, fz_rect *rect)
-{
- if (doc && doc->bound_annot && annot && rect)
- return doc->bound_annot(doc, annot, rect);
- if (rect)
- *rect = fz_empty_rect;
- return rect;
-}
-
-void
-fz_run_page_contents(fz_document *doc, fz_page *page, fz_device *dev, const fz_matrix *transform, fz_cookie *cookie)
-{
- if (doc && doc->run_page_contents && page)
- doc->run_page_contents(doc, page, dev, transform, cookie);
-}
-
-void
-fz_run_annot(fz_document *doc, fz_page *page, fz_annot *annot, fz_device *dev, const fz_matrix *transform, fz_cookie *cookie)
-{
- if (doc && doc->run_annot && page && annot)
- doc->run_annot(doc, page, annot, dev, transform, cookie);
-}
-
-void
-fz_run_page(fz_document *doc, fz_page *page, fz_device *dev, const fz_matrix *transform, fz_cookie *cookie)
-{
- fz_annot *annot;
- fz_rect mediabox;
-
- fz_bound_page(doc, page, &mediabox);
- fz_begin_page(dev, &mediabox, transform);
-
- fz_run_page_contents(doc, page, dev, transform, cookie);
-
- if (cookie && cookie->progress_max != -1)
- {
- int count = 1;
- for (annot = fz_first_annot(doc, page); annot; annot = fz_next_annot(doc, annot))
- count++;
- cookie->progress_max += count;
- }
-
- for (annot = fz_first_annot(doc, page); annot; annot = fz_next_annot(doc, annot))
- {
- /* Check the cookie for aborting */
- if (cookie)
- {
- if (cookie->abort)
- break;
- cookie->progress++;
- }
-
- fz_run_annot(doc, page, annot, dev, transform, cookie);
- }
-
- fz_end_page(dev);
-}
-
-void
-fz_free_page(fz_document *doc, fz_page *page)
-{
- if (doc && doc->free_page && page)
- doc->free_page(doc, page);
-}
-
-int
-fz_meta(fz_document *doc, int key, void *ptr, int size)
-{
- if (doc && doc->meta)
- return doc->meta(doc, key, ptr, size);
- return FZ_META_UNKNOWN_KEY;
-}
-
-fz_transition *
-fz_page_presentation(fz_document *doc, fz_page *page, float *duration)
-{
- float dummy;
- if (duration)
- *duration = 0;
- else
- duration = &dummy;
- if (doc && doc->page_presentation && page)
- return doc->page_presentation(doc, page, duration);
- return NULL;
-}
-
-int fz_javascript_supported(void)
-{
- return pdf_js_supported();
-}
-
-void
-fz_write_document(fz_document *doc, char *filename, fz_write_options *opts)
-{
- if (doc && doc->write)
- doc->write(doc, filename, opts);
-}
diff --git a/fitz/doc_link.c b/fitz/doc_link.c
deleted file mode 100644
index 30dca222..00000000
--- a/fitz/doc_link.c
+++ /dev/null
@@ -1,65 +0,0 @@
-#include "mupdf/fitz.h"
-
-void
-fz_free_link_dest(fz_context *ctx, fz_link_dest *dest)
-{
- switch (dest->kind)
- {
- case FZ_LINK_NONE:
- case FZ_LINK_GOTO:
- break;
- case FZ_LINK_URI:
- fz_free(ctx, dest->ld.uri.uri);
- break;
- case FZ_LINK_LAUNCH:
- fz_free(ctx, dest->ld.launch.file_spec);
- break;
- case FZ_LINK_NAMED:
- fz_free(ctx, dest->ld.named.named);
- break;
- case FZ_LINK_GOTOR:
- fz_free(ctx, dest->ld.gotor.file_spec);
- break;
- }
-}
-
-fz_link *
-fz_new_link(fz_context *ctx, const fz_rect *bbox, fz_link_dest dest)
-{
- fz_link *link;
-
- fz_try(ctx)
- {
- link = fz_malloc_struct(ctx, fz_link);
- link->refs = 1;
- }
- fz_catch(ctx)
- {
- fz_free_link_dest(ctx, &dest);
- fz_rethrow(ctx);
- }
- link->dest = dest;
- link->rect = *bbox;
- link->next = NULL;
- return link;
-}
-
-fz_link *
-fz_keep_link(fz_context *ctx, fz_link *link)
-{
- if (link)
- link->refs++;
- return link;
-}
-
-void
-fz_drop_link(fz_context *ctx, fz_link *link)
-{
- while (link && --link->refs == 0)
- {
- fz_link *next = link->next;
- fz_free_link_dest(ctx, &link->dest);
- fz_free(ctx, link);
- link = next;
- }
-}
diff --git a/fitz/doc_outline.c b/fitz/doc_outline.c
deleted file mode 100644
index e26fd378..00000000
--- a/fitz/doc_outline.c
+++ /dev/null
@@ -1,62 +0,0 @@
-#include "mupdf/fitz.h"
-
-void
-fz_free_outline(fz_context *ctx, fz_outline *outline)
-{
- while (outline)
- {
- fz_outline *next = outline->next;
- fz_free_outline(ctx, outline->down);
- fz_free(ctx, outline->title);
- fz_free_link_dest(ctx, &outline->dest);
- fz_free(ctx, outline);
- outline = next;
- }
-}
-
-static void
-do_debug_outline_xml(fz_output *out, fz_outline *outline, int level)
-{
- while (outline)
- {
- fz_printf(out, "<outline title=\"%s\" page=\"%d\"", outline->title, outline->dest.kind == FZ_LINK_GOTO ? outline->dest.ld.gotor.page + 1 : 0);
- if (outline->down)
- {
- fz_printf(out, ">\n");
- do_debug_outline_xml(out, outline->down, level + 1);
- fz_printf(out, "</outline>\n");
- }
- else
- {
- fz_printf(out, " />\n");
- }
- outline = outline->next;
- }
-}
-
-void
-fz_print_outline_xml(fz_context *ctx, fz_output *out, fz_outline *outline)
-{
- do_debug_outline_xml(out, outline, 0);
-}
-
-static void
-do_debug_outline(fz_output *out, fz_outline *outline, int level)
-{
- int i;
- while (outline)
- {
- for (i = 0; i < level; i++)
- fz_printf(out, "\t");
- fz_printf(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(out, outline->down, level + 1);
- outline = outline->next;
- }
-}
-
-void
-fz_print_outline(fz_context *ctx, fz_output *out, fz_outline *outline)
-{
- do_debug_outline(out, outline, 0);
-}
diff --git a/fitz/filt_basic.c b/fitz/filt_basic.c
deleted file mode 100644
index 3968d193..00000000
--- a/fitz/filt_basic.c
+++ /dev/null
@@ -1,662 +0,0 @@
-#include "mupdf/fitz.h"
-
-/* Pretend we have a filter that just copies data forever */
-
-fz_stream *
-fz_open_copy(fz_stream *chain)
-{
- return fz_keep_stream(chain);
-}
-
-/* Null filter copies a specified amount of data */
-
-struct null_filter
-{
- fz_stream *chain;
- int remain;
- int pos;
-};
-
-static int
-read_null(fz_stream *stm, unsigned char *buf, int len)
-{
- struct null_filter *state = stm->state;
- int amount = fz_mini(len, state->remain);
- int n;
-
- fz_seek(state->chain, state->pos, 0);
- n = fz_read(state->chain, buf, amount);
- state->remain -= n;
- state->pos += n;
- return n;
-}
-
-static void
-close_null(fz_context *ctx, void *state_)
-{
- struct null_filter *state = (struct null_filter *)state_;
- fz_stream *chain = state->chain;
- fz_free(ctx, state);
- fz_close(chain);
-}
-
-fz_stream *
-fz_open_null(fz_stream *chain, int len, int offset)
-{
- struct null_filter *state;
- fz_context *ctx = chain->ctx;
-
- if (len < 0)
- len = 0;
- fz_try(ctx)
- {
- state = fz_malloc_struct(ctx, struct null_filter);
- state->chain = chain;
- state->remain = len;
- state->pos = offset;
- }
- fz_catch(ctx)
- {
- fz_close(chain);
- fz_rethrow(ctx);
- }
-
- return fz_new_stream(ctx, state, read_null, close_null);
-}
-
-/* Concat filter concatenates several streams into one */
-
-struct concat_filter
-{
- int max;
- int count;
- int current;
- int pad; /* 1 if we should add whitespace padding between streams */
- int ws; /* 1 if we should send a whitespace padding byte next */
- fz_stream *chain[1];
-};
-
-static int
-read_concat(fz_stream *stm, unsigned char *buf, int len)
-{
- struct concat_filter *state = (struct concat_filter *)stm->state;
- int n;
- int read = 0;
-
- if (len <= 0)
- return 0;
-
- while (state->current != state->count && len > 0)
- {
- /* If we need to send a whitespace char, do that */
- if (state->ws)
- {
- *buf++ = 32;
- read++;
- len--;
- state->ws = 0;
- continue;
- }
- /* Otherwise, read as much data as will fit in the buffer */
- n = fz_read(state->chain[state->current], buf, len);
- read += n;
- buf += n;
- len -= n;
- /* If we didn't read any, then we must have hit the end of
- * our buffer space. Move to the next stream, and remember to
- * pad. */
- if (n == 0)
- {
- fz_close(state->chain[state->current]);
- state->current++;
- state->ws = state->pad;
- }
- }
-
- return read;
-}
-
-static void
-close_concat(fz_context *ctx, void *state_)
-{
- struct concat_filter *state = (struct concat_filter *)state_;
- int i;
-
- for (i = state->current; i < state->count; i++)
- {
- fz_close(state->chain[i]);
- }
- fz_free(ctx, state);
-}
-
-fz_stream *
-fz_open_concat(fz_context *ctx, int len, int pad)
-{
- struct concat_filter *state;
-
- state = fz_calloc(ctx, 1, sizeof(struct concat_filter) + (len-1)*sizeof(fz_stream *));
- state->max = len;
- state->count = 0;
- state->current = 0;
- state->pad = pad;
- state->ws = 0; /* We never send padding byte at the start */
-
- return fz_new_stream(ctx, state, read_concat, close_concat);
-}
-
-void
-fz_concat_push(fz_stream *concat, fz_stream *chain)
-{
- struct concat_filter *state = (struct concat_filter *)concat->state;
-
- if (state->count == state->max)
- fz_throw(concat->ctx, FZ_ERROR_GENERIC, "Concat filter size exceeded");
-
- state->chain[state->count++] = chain;
-}
-
-/* ASCII Hex Decode */
-
-typedef struct fz_ahxd_s fz_ahxd;
-
-struct fz_ahxd_s
-{
- fz_stream *chain;
- int eod;
-};
-
-static inline int iswhite(int a)
-{
- switch (a) {
- case '\n': case '\r': case '\t': case ' ':
- case '\0': case '\f': case '\b': case 0177:
- return 1;
- }
- return 0;
-}
-
-static inline int ishex(int a)
-{
- return (a >= 'A' && a <= 'F') ||
- (a >= 'a' && a <= 'f') ||
- (a >= '0' && a <= '9');
-}
-
-static inline int unhex(int a)
-{
- if (a >= 'A' && a <= 'F') return a - 'A' + 0xA;
- if (a >= 'a' && a <= 'f') return a - 'a' + 0xA;
- if (a >= '0' && a <= '9') return a - '0';
- return 0;
-}
-
-static int
-read_ahxd(fz_stream *stm, unsigned char *buf, int len)
-{
- fz_ahxd *state = stm->state;
- unsigned char *p = buf;
- unsigned char *ep = buf + len;
- int a, b, c, odd;
-
- odd = 0;
-
- while (p < ep)
- {
- if (state->eod)
- return p - buf;
-
- c = fz_read_byte(state->chain);
- if (c < 0)
- return p - buf;
-
- if (ishex(c))
- {
- if (!odd)
- {
- a = unhex(c);
- odd = 1;
- }
- else
- {
- b = unhex(c);
- *p++ = (a << 4) | b;
- odd = 0;
- }
- }
- else if (c == '>')
- {
- if (odd)
- *p++ = (a << 4);
- state->eod = 1;
- }
- else if (!iswhite(c))
- {
- fz_throw(stm->ctx, FZ_ERROR_GENERIC, "bad data in ahxd: '%c'", c);
- }
- }
-
- return p - buf;
-}
-
-static void
-close_ahxd(fz_context *ctx, void *state_)
-{
- fz_ahxd *state = (fz_ahxd *)state_;
- fz_stream *chain = state->chain;
- fz_free(ctx, state);
- fz_close(chain);
-}
-
-fz_stream *
-fz_open_ahxd(fz_stream *chain)
-{
- fz_ahxd *state;
- fz_context *ctx = chain->ctx;
-
- fz_try(ctx)
- {
- state = fz_malloc_struct(ctx, fz_ahxd);
- state->chain = chain;
- state->eod = 0;
- }
- fz_catch(ctx)
- {
- fz_close(chain);
- fz_rethrow(ctx);
- }
-
- return fz_new_stream(ctx, state, read_ahxd, close_ahxd);
-}
-
-/* ASCII 85 Decode */
-
-typedef struct fz_a85d_s fz_a85d;
-
-struct fz_a85d_s
-{
- fz_stream *chain;
- unsigned char bp[4];
- unsigned char *rp, *wp;
- int eod;
-};
-
-static int
-read_a85d(fz_stream *stm, unsigned char *buf, int len)
-{
- fz_a85d *state = stm->state;
- unsigned char *p = buf;
- unsigned char *ep = buf + len;
- int count = 0;
- int word = 0;
- int c;
-
- while (state->rp < state->wp && p < ep)
- *p++ = *state->rp++;
-
- while (p < ep)
- {
- if (state->eod)
- return p - buf;
-
- c = fz_read_byte(state->chain);
- if (c < 0)
- return p - buf;
-
- if (c >= '!' && c <= 'u')
- {
- if (count == 4)
- {
- word = word * 85 + (c - '!');
-
- state->bp[0] = (word >> 24) & 0xff;
- state->bp[1] = (word >> 16) & 0xff;
- state->bp[2] = (word >> 8) & 0xff;
- state->bp[3] = (word) & 0xff;
- state->rp = state->bp;
- state->wp = state->bp + 4;
-
- word = 0;
- count = 0;
- }
- else
- {
- word = word * 85 + (c - '!');
- count ++;
- }
- }
-
- else if (c == 'z' && count == 0)
- {
- state->bp[0] = 0;
- state->bp[1] = 0;
- state->bp[2] = 0;
- state->bp[3] = 0;
- state->rp = state->bp;
- state->wp = state->bp + 4;
- }
-
- else if (c == '~')
- {
- c = fz_read_byte(state->chain);
- if (c != '>')
- fz_warn(stm->ctx, "bad eod marker in a85d");
-
- switch (count) {
- case 0:
- break;
- case 1:
- /* Specifically illegal in the spec, but adobe
- * and gs both cope. See normal_87.pdf for a
- * case where this matters. */
- fz_warn(stm->ctx, "partial final byte in a85d");
- break;
- case 2:
- word = word * (85 * 85 * 85) + 0xffffff;
- state->bp[0] = word >> 24;
- state->rp = state->bp;
- state->wp = state->bp + 1;
- break;
- case 3:
- word = word * (85 * 85) + 0xffff;
- state->bp[0] = word >> 24;
- state->bp[1] = word >> 16;
- state->rp = state->bp;
- state->wp = state->bp + 2;
- break;
- case 4:
- word = word * 85 + 0xff;
- state->bp[0] = word >> 24;
- state->bp[1] = word >> 16;
- state->bp[2] = word >> 8;
- state->rp = state->bp;
- state->wp = state->bp + 3;
- break;
- }
- state->eod = 1;
- }
-
- else if (!iswhite(c))
- {
- fz_throw(stm->ctx, FZ_ERROR_GENERIC, "bad data in a85d: '%c'", c);
- }
-
- while (state->rp < state->wp && p < ep)
- *p++ = *state->rp++;
- }
-
- return p - buf;
-}
-
-static void
-close_a85d(fz_context *ctx, void *state_)
-{
- fz_a85d *state = (fz_a85d *)state_;
- fz_stream *chain = state->chain;
-
- fz_free(ctx, state);
- fz_close(chain);
-}
-
-fz_stream *
-fz_open_a85d(fz_stream *chain)
-{
- fz_a85d *state;
- fz_context *ctx = chain->ctx;
-
- fz_try(ctx)
- {
- state = fz_malloc_struct(ctx, fz_a85d);
- state->chain = chain;
- state->rp = state->bp;
- state->wp = state->bp;
- state->eod = 0;
- }
- fz_catch(ctx)
- {
- fz_close(chain);
- fz_rethrow(ctx);
- }
-
- return fz_new_stream(ctx, state, read_a85d, close_a85d);
-}
-
-/* Run Length Decode */
-
-typedef struct fz_rld_s fz_rld;
-
-struct fz_rld_s
-{
- fz_stream *chain;
- int run, n, c;
-};
-
-static int
-read_rld(fz_stream *stm, unsigned char *buf, int len)
-{
- fz_rld *state = stm->state;
- unsigned char *p = buf;
- unsigned char *ep = buf + len;
-
- while (p < ep)
- {
- if (state->run == 128)
- return p - buf;
-
- if (state->n == 0)
- {
- state->run = fz_read_byte(state->chain);
- if (state->run < 0)
- state->run = 128;
- if (state->run < 128)
- state->n = state->run + 1;
- if (state->run > 128)
- {
- state->n = 257 - state->run;
- state->c = fz_read_byte(state->chain);
- if (state->c < 0)
- fz_throw(stm->ctx, FZ_ERROR_GENERIC, "premature end of data in run length decode");
- }
- }
-
- if (state->run < 128)
- {
- while (p < ep && state->n)
- {
- int c = fz_read_byte(state->chain);
- if (c < 0)
- fz_throw(stm->ctx, FZ_ERROR_GENERIC, "premature end of data in run length decode");
- *p++ = c;
- state->n--;
- }
- }
-
- if (state->run > 128)
- {
- while (p < ep && state->n)
- {
- *p++ = state->c;
- state->n--;
- }
- }
- }
-
- return p - buf;
-}
-
-static void
-close_rld(fz_context *ctx, void *state_)
-{
- fz_rld *state = (fz_rld *)state_;
- fz_stream *chain = state->chain;
-
- fz_free(ctx, state);
- fz_close(chain);
-}
-
-fz_stream *
-fz_open_rld(fz_stream *chain)
-{
- fz_rld *state;
- fz_context *ctx = chain->ctx;
-
- fz_try(ctx)
- {
- state = fz_malloc_struct(ctx, fz_rld);
- state->chain = chain;
- state->run = 0;
- state->n = 0;
- state->c = 0;
- }
- fz_catch(ctx)
- {
- fz_close(chain);
- fz_rethrow(ctx);
- }
-
- return fz_new_stream(ctx, state, read_rld, close_rld);
-}
-
-/* RC4 Filter */
-
-typedef struct fz_arc4c_s fz_arc4c;
-
-struct fz_arc4c_s
-{
- fz_stream *chain;
- fz_arc4 arc4;
-};
-
-static int
-read_arc4(fz_stream *stm, unsigned char *buf, int len)
-{
- fz_arc4c *state = stm->state;
- int n = fz_read(state->chain, buf, len);
- fz_arc4_encrypt(&state->arc4, buf, buf, n);
- return n;
-}
-
-static void
-close_arc4(fz_context *ctx, void *state_)
-{
- fz_arc4c *state = (fz_arc4c *)state_;
- fz_stream *chain = state->chain;
-
- fz_free(ctx, state);
- fz_close(chain);
-}
-
-fz_stream *
-fz_open_arc4(fz_stream *chain, unsigned char *key, unsigned keylen)
-{
- fz_arc4c *state;
- fz_context *ctx = chain->ctx;
-
- fz_try(ctx)
- {
- state = fz_malloc_struct(ctx, fz_arc4c);
- state->chain = chain;
- fz_arc4_init(&state->arc4, key, keylen);
- }
- fz_catch(ctx)
- {
- fz_close(chain);
- fz_rethrow(ctx);
- }
-
- return fz_new_stream(ctx, state, read_arc4, close_arc4);
-}
-
-/* AES Filter */
-
-typedef struct fz_aesd_s fz_aesd;
-
-struct fz_aesd_s
-{
- fz_stream *chain;
- fz_aes aes;
- unsigned char iv[16];
- int ivcount;
- unsigned char bp[16];
- unsigned char *rp, *wp;
-};
-
-static int
-read_aesd(fz_stream *stm, unsigned char *buf, int len)
-{
- fz_aesd *state = stm->state;
- unsigned char *p = buf;
- unsigned char *ep = buf + len;
-
- while (state->ivcount < 16)
- {
- int c = fz_read_byte(state->chain);
- if (c < 0)
- fz_throw(stm->ctx, FZ_ERROR_GENERIC, "premature end in aes filter");
- state->iv[state->ivcount++] = c;
- }
-
- while (state->rp < state->wp && p < ep)
- *p++ = *state->rp++;
-
- while (p < ep)
- {
- int n = fz_read(state->chain, state->bp, 16);
- if (n == 0)
- return p - buf;
- else if (n < 16)
- fz_throw(stm->ctx, FZ_ERROR_GENERIC, "partial block in aes filter");
-
- aes_crypt_cbc(&state->aes, AES_DECRYPT, 16, state->iv, state->bp, state->bp);
- state->rp = state->bp;
- state->wp = state->bp + 16;
-
- /* strip padding at end of file */
- if (fz_is_eof(state->chain))
- {
- int pad = state->bp[15];
- if (pad < 1 || pad > 16)
- fz_throw(stm->ctx, FZ_ERROR_GENERIC, "aes padding out of range: %d", pad);
- state->wp -= pad;
- }
-
- while (state->rp < state->wp && p < ep)
- *p++ = *state->rp++;
- }
-
- return p - buf;
-}
-
-static void
-close_aesd(fz_context *ctx, void *state_)
-{
- fz_aesd *state = (fz_aesd *)state_;
- fz_stream *chain = state->chain;
-
- fz_free(ctx, state);
- fz_close(chain);
-}
-
-fz_stream *
-fz_open_aesd(fz_stream *chain, unsigned char *key, unsigned keylen)
-{
- fz_aesd *state;
- fz_context *ctx = chain->ctx;
-
- fz_try(ctx)
- {
- state = fz_malloc_struct(ctx, fz_aesd);
- state->chain = chain;
- if (aes_setkey_dec(&state->aes, key, keylen * 8))
- fz_throw(ctx, FZ_ERROR_GENERIC, "AES key init failed (keylen=%d)", keylen * 8);
- state->ivcount = 0;
- state->rp = state->bp;
- state->wp = state->bp;
- }
- fz_catch(ctx)
- {
- fz_close(chain);
- fz_rethrow(ctx);
- }
-
- return fz_new_stream(ctx, state, read_aesd, close_aesd);
-}
diff --git a/fitz/filt_dctd.c b/fitz/filt_dctd.c
deleted file mode 100644
index 1a55e584..00000000
--- a/fitz/filt_dctd.c
+++ /dev/null
@@ -1,256 +0,0 @@
-#include "mupdf/fitz.h"
-
-#include <jpeglib.h>
-#include <setjmp.h>
-
-typedef struct fz_dctd_s fz_dctd;
-
-struct fz_dctd_s
-{
- fz_stream *chain;
- fz_context *ctx;
- int color_transform;
- int init;
- int stride;
- int l2factor;
- unsigned char *scanline;
- unsigned char *rp, *wp;
- struct jpeg_decompress_struct cinfo;
- struct jpeg_source_mgr srcmgr;
- struct jpeg_error_mgr errmgr;
- jmp_buf jb;
- char msg[JMSG_LENGTH_MAX];
-};
-
-static void error_exit(j_common_ptr cinfo)
-{
- fz_dctd *state = cinfo->client_data;
- cinfo->err->format_message(cinfo, state->msg);
- longjmp(state->jb, 1);
-}
-
-static void init_source(j_decompress_ptr cinfo)
-{
- /* nothing to do */
-}
-
-static void term_source(j_decompress_ptr cinfo)
-{
- /* nothing to do */
-}
-
-static boolean fill_input_buffer(j_decompress_ptr cinfo)
-{
- struct jpeg_source_mgr *src = cinfo->src;
- fz_dctd *state = cinfo->client_data;
- fz_stream *chain = state->chain;
- fz_context *ctx = chain->ctx;
-
- chain->rp = chain->wp;
- fz_try(ctx)
- {
- fz_fill_buffer(chain);
- }
- fz_catch(ctx)
- {
- /* FIXME: TRYLATER */
- return 0;
- }
- src->next_input_byte = chain->rp;
- src->bytes_in_buffer = chain->wp - chain->rp;
-
- if (src->bytes_in_buffer == 0)
- {
- static unsigned char eoi[2] = { 0xFF, JPEG_EOI };
- fz_warn(state->ctx, "premature end of file in jpeg");
- src->next_input_byte = eoi;
- src->bytes_in_buffer = 2;
- }
-
- return 1;
-}
-
-static void skip_input_data(j_decompress_ptr cinfo, long num_bytes)
-{
- struct jpeg_source_mgr *src = cinfo->src;
- if (num_bytes > 0)
- {
- while ((size_t)num_bytes > src->bytes_in_buffer)
- {
- num_bytes -= src->bytes_in_buffer;
- (void) src->fill_input_buffer(cinfo);
- }
- src->next_input_byte += num_bytes;
- src->bytes_in_buffer -= num_bytes;
- }
-}
-
-static int
-read_dctd(fz_stream *stm, unsigned char *buf, int len)
-{
- fz_dctd *state = stm->state;
- j_decompress_ptr cinfo = &state->cinfo;
- unsigned char *p = buf;
- unsigned char *ep = buf + len;
-
- if (setjmp(state->jb))
- {
- if (cinfo->src)
- state->chain->rp = state->chain->wp - cinfo->src->bytes_in_buffer;
- fz_throw(stm->ctx, FZ_ERROR_GENERIC, "jpeg error: %s", state->msg);
- }
-
- if (!state->init)
- {
- int c;
- cinfo->client_data = state;
- cinfo->err = &state->errmgr;
- jpeg_std_error(cinfo->err);
- cinfo->err->error_exit = error_exit;
- jpeg_create_decompress(cinfo);
- state->init = 1;
-
- /* Skip over any stray returns at the start of the stream */
- while ((c = fz_peek_byte(state->chain)) == '\n' || c == '\r')
- (void)fz_read_byte(state->chain);
-
- cinfo->src = &state->srcmgr;
- cinfo->src->init_source = init_source;
- cinfo->src->fill_input_buffer = fill_input_buffer;
- cinfo->src->skip_input_data = skip_input_data;
- cinfo->src->resync_to_restart = jpeg_resync_to_restart;
- cinfo->src->term_source = term_source;
- cinfo->src->next_input_byte = state->chain->rp;
- cinfo->src->bytes_in_buffer = state->chain->wp - state->chain->rp;
-
- jpeg_read_header(cinfo, 1);
-
- /* speed up jpeg decoding a bit */
- cinfo->dct_method = JDCT_FASTEST;
- cinfo->do_fancy_upsampling = FALSE;
-
- /* default value if ColorTransform is not set */
- if (state->color_transform == -1)
- {
- if (state->cinfo.num_components == 3)
- state->color_transform = 1;
- else
- state->color_transform = 0;
- }
-
- if (cinfo->saw_Adobe_marker)
- state->color_transform = cinfo->Adobe_transform;
-
- /* Guess the input colorspace, and set output colorspace accordingly */
- switch (cinfo->num_components)
- {
- case 3:
- if (state->color_transform)
- cinfo->jpeg_color_space = JCS_YCbCr;
- else
- cinfo->jpeg_color_space = JCS_RGB;
- break;
- case 4:
- if (state->color_transform)
- cinfo->jpeg_color_space = JCS_YCCK;
- else
- cinfo->jpeg_color_space = JCS_CMYK;
- break;
- }
-
- cinfo->scale_num = 8/(1<<state->l2factor);
- cinfo->scale_denom = 8;
-
- jpeg_start_decompress(cinfo);
-
- state->stride = cinfo->output_width * cinfo->output_components;
- state->scanline = fz_malloc(state->ctx, state->stride);
- state->rp = state->scanline;
- state->wp = state->scanline;
- }
-
- while (state->rp < state->wp && p < ep)
- *p++ = *state->rp++;
-
- while (p < ep)
- {
- if (cinfo->output_scanline == cinfo->output_height)
- break;
-
- if (p + state->stride <= ep)
- {
- jpeg_read_scanlines(cinfo, &p, 1);
- p += state->stride;
- }
- else
- {
- jpeg_read_scanlines(cinfo, &state->scanline, 1);
- state->rp = state->scanline;
- state->wp = state->scanline + state->stride;
- }
-
- while (state->rp < state->wp && p < ep)
- *p++ = *state->rp++;
- }
-
- return p - buf;
-}
-
-static void
-close_dctd(fz_context *ctx, void *state_)
-{
- fz_dctd *state = (fz_dctd *)state_;
-
- if (setjmp(state->jb))
- {
- fz_warn(ctx, "jpeg error: %s", state->msg);
- goto skip;
- }
-
- if (state->init)
- jpeg_finish_decompress(&state->cinfo);
-
-skip:
- if (state->cinfo.src)
- state->chain->rp = state->chain->wp - state->cinfo.src->bytes_in_buffer;
- if (state->init)
- jpeg_destroy_decompress(&state->cinfo);
-
- fz_free(ctx, state->scanline);
- fz_close(state->chain);
- fz_free(ctx, state);
-}
-
-/* Default: color_transform = -1 (unset) */
-fz_stream *
-fz_open_dctd(fz_stream *chain, int color_transform)
-{
- return fz_open_resized_dctd(chain, color_transform, 0);
-}
-
-fz_stream *
-fz_open_resized_dctd(fz_stream *chain, int color_transform, int l2factor)
-{
- fz_context *ctx = chain->ctx;
- fz_dctd *state = NULL;
-
- fz_var(state);
-
- fz_try(ctx)
- {
- state = fz_malloc_struct(chain->ctx, fz_dctd);
- state->ctx = ctx;
- state->chain = chain;
- state->color_transform = color_transform;
- state->init = 0;
- state->l2factor = l2factor;
- }
- fz_catch(ctx)
- {
- fz_free(ctx, state);
- fz_close(chain);
- fz_rethrow(ctx);
- }
-
- return fz_new_stream(ctx, state, read_dctd, close_dctd);
-}
diff --git a/fitz/filt_faxd.c b/fitz/filt_faxd.c
deleted file mode 100644
index 8ac98f42..00000000
--- a/fitz/filt_faxd.c
+++ /dev/null
@@ -1,776 +0,0 @@
-#include "mupdf/fitz.h"
-
-/* Fax G3/G4 decoder */
-
-/* TODO: uncompressed */
-
-/*
-<raph> the first 2^(initialbits) entries map bit patterns to decodes
-<raph> let's say initial_bits is 8 for the sake of example
-<raph> and that the code is 1001
-<raph> that means that entries 0x90 .. 0x9f have the entry { val, 4 }
-<raph> because those are all the bytes that start with the code
-<raph> and the 4 is the length of the code
-... if (n_bits > initial_bits) ...
-<raph> anyway, in that case, it basically points to a mini table
-<raph> the n_bits is the maximum length of all codes beginning with that byte
-<raph> so 2^(n_bits - initial_bits) is the size of the mini-table
-<raph> peter came up with this, and it makes sense
-*/
-
-typedef struct cfd_node_s cfd_node;
-
-struct cfd_node_s
-{
- short val;
- short nbits;
-};
-
-enum
-{
- cfd_white_initial_bits = 8,
- cfd_black_initial_bits = 7,
- cfd_2d_initial_bits = 7,
- cfd_uncompressed_initial_bits = 6 /* must be 6 */
-};
-
-/* non-run codes in tables */
-enum
-{
- ERROR = -1,
- ZEROS = -2, /* EOL follows, possibly with more padding first */
- UNCOMPRESSED = -3
-};
-
-/* semantic codes for cf_2d_decode */
-enum
-{
- P = -4,
- H = -5,
- VR3 = 0,
- VR2 = 1,
- VR1 = 2,
- V0 = 3,
- VL1 = 4,
- VL2 = 5,
- VL3 = 6
-};
-
-/* White decoding table. */
-static const cfd_node cf_white_decode[] = {
- {256,12},{272,12},{29,8},{30,8},{45,8},{46,8},{22,7},{22,7},
- {23,7},{23,7},{47,8},{48,8},{13,6},{13,6},{13,6},{13,6},{20,7},
- {20,7},{33,8},{34,8},{35,8},{36,8},{37,8},{38,8},{19,7},{19,7},
- {31,8},{32,8},{1,6},{1,6},{1,6},{1,6},{12,6},{12,6},{12,6},{12,6},
- {53,8},{54,8},{26,7},{26,7},{39,8},{40,8},{41,8},{42,8},{43,8},
- {44,8},{21,7},{21,7},{28,7},{28,7},{61,8},{62,8},{63,8},{0,8},
- {320,8},{384,8},{10,5},{10,5},{10,5},{10,5},{10,5},{10,5},{10,5},
- {10,5},{11,5},{11,5},{11,5},{11,5},{11,5},{11,5},{11,5},{11,5},
- {27,7},{27,7},{59,8},{60,8},{288,9},{290,9},{18,7},{18,7},{24,7},
- {24,7},{49,8},{50,8},{51,8},{52,8},{25,7},{25,7},{55,8},{56,8},
- {57,8},{58,8},{192,6},{192,6},{192,6},{192,6},{1664,6},{1664,6},
- {1664,6},{1664,6},{448,8},{512,8},{292,9},{640,8},{576,8},{294,9},
- {296,9},{298,9},{300,9},{302,9},{256,7},{256,7},{2,4},{2,4},{2,4},
- {2,4},{2,4},{2,4},{2,4},{2,4},{2,4},{2,4},{2,4},{2,4},{2,4},{2,4},
- {2,4},{2,4},{3,4},{3,4},{3,4},{3,4},{3,4},{3,4},{3,4},{3,4},{3,4},
- {3,4},{3,4},{3,4},{3,4},{3,4},{3,4},{3,4},{128,5},{128,5},{128,5},
- {128,5},{128,5},{128,5},{128,5},{128,5},{8,5},{8,5},{8,5},{8,5},
- {8,5},{8,5},{8,5},{8,5},{9,5},{9,5},{9,5},{9,5},{9,5},{9,5},{9,5},
- {9,5},{16,6},{16,6},{16,6},{16,6},{17,6},{17,6},{17,6},{17,6},
- {4,4},{4,4},{4,4},{4,4},{4,4},{4,4},{4,4},{4,4},{4,4},{4,4},{4,4},
- {4,4},{4,4},{4,4},{4,4},{4,4},{5,4},{5,4},{5,4},{5,4},{5,4},{5,4},
- {5,4},{5,4},{5,4},{5,4},{5,4},{5,4},{5,4},{5,4},{5,4},{5,4},
- {14,6},{14,6},{14,6},{14,6},{15,6},{15,6},{15,6},{15,6},{64,5},
- {64,5},{64,5},{64,5},{64,5},{64,5},{64,5},{64,5},{6,4},{6,4},
- {6,4},{6,4},{6,4},{6,4},{6,4},{6,4},{6,4},{6,4},{6,4},{6,4},{6,4},
- {6,4},{6,4},{6,4},{7,4},{7,4},{7,4},{7,4},{7,4},{7,4},{7,4},{7,4},
- {7,4},{7,4},{7,4},{7,4},{7,4},{7,4},{7,4},{7,4},{-2,3},{-2,3},
- {-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},
- {-1,0},{-1,0},{-1,0},{-1,0},{-3,4},{1792,3},{1792,3},{1984,4},
- {2048,4},{2112,4},{2176,4},{2240,4},{2304,4},{1856,3},{1856,3},
- {1920,3},{1920,3},{2368,4},{2432,4},{2496,4},{2560,4},{1472,1},
- {1536,1},{1600,1},{1728,1},{704,1},{768,1},{832,1},{896,1},
- {960,1},{1024,1},{1088,1},{1152,1},{1216,1},{1280,1},{1344,1},
- {1408,1}
-};
-
-/* Black decoding table. */
-static const cfd_node cf_black_decode[] = {
- {128,12},{160,13},{224,12},{256,12},{10,7},{11,7},{288,12},{12,7},
- {9,6},{9,6},{8,6},{8,6},{7,5},{7,5},{7,5},{7,5},{6,4},{6,4},{6,4},
- {6,4},{6,4},{6,4},{6,4},{6,4},{5,4},{5,4},{5,4},{5,4},{5,4},{5,4},
- {5,4},{5,4},{1,3},{1,3},{1,3},{1,3},{1,3},{1,3},{1,3},{1,3},{1,3},
- {1,3},{1,3},{1,3},{1,3},{1,3},{1,3},{1,3},{4,3},{4,3},{4,3},{4,3},
- {4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},
- {4,3},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},
- {3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},
- {3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},
- {2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},
- {2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},
- {2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},
- {-2,4},{-2,4},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},
- {-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-3,5},{1792,4},
- {1792,4},{1984,5},{2048,5},{2112,5},{2176,5},{2240,5},{2304,5},
- {1856,4},{1856,4},{1920,4},{1920,4},{2368,5},{2432,5},{2496,5},
- {2560,5},{18,3},{18,3},{18,3},{18,3},{18,3},{18,3},{18,3},{18,3},
- {52,5},{52,5},{640,6},{704,6},{768,6},{832,6},{55,5},{55,5},
- {56,5},{56,5},{1280,6},{1344,6},{1408,6},{1472,6},{59,5},{59,5},
- {60,5},{60,5},{1536,6},{1600,6},{24,4},{24,4},{24,4},{24,4},
- {25,4},{25,4},{25,4},{25,4},{1664,6},{1728,6},{320,5},{320,5},
- {384,5},{384,5},{448,5},{448,5},{512,6},{576,6},{53,5},{53,5},
- {54,5},{54,5},{896,6},{960,6},{1024,6},{1088,6},{1152,6},{1216,6},
- {64,3},{64,3},{64,3},{64,3},{64,3},{64,3},{64,3},{64,3},{13,1},
- {13,1},{13,1},{13,1},{13,1},{13,1},{13,1},{13,1},{13,1},{13,1},
- {13,1},{13,1},{13,1},{13,1},{13,1},{13,1},{23,4},{23,4},{50,5},
- {51,5},{44,5},{45,5},{46,5},{47,5},{57,5},{58,5},{61,5},{256,5},
- {16,3},{16,3},{16,3},{16,3},{17,3},{17,3},{17,3},{17,3},{48,5},
- {49,5},{62,5},{63,5},{30,5},{31,5},{32,5},{33,5},{40,5},{41,5},
- {22,4},{22,4},{14,1},{14,1},{14,1},{14,1},{14,1},{14,1},{14,1},
- {14,1},{14,1},{14,1},{14,1},{14,1},{14,1},{14,1},{14,1},{14,1},
- {15,2},{15,2},{15,2},{15,2},{15,2},{15,2},{15,2},{15,2},{128,5},
- {192,5},{26,5},{27,5},{28,5},{29,5},{19,4},{19,4},{20,4},{20,4},
- {34,5},{35,5},{36,5},{37,5},{38,5},{39,5},{21,4},{21,4},{42,5},
- {43,5},{0,3},{0,3},{0,3},{0,3}
-};
-
-/* 2-D decoding table. */
-static const cfd_node cf_2d_decode[] = {
- {128,11},{144,10},{6,7},{0,7},{5,6},{5,6},{1,6},{1,6},{-4,4},
- {-4,4},{-4,4},{-4,4},{-4,4},{-4,4},{-4,4},{-4,4},{-5,3},{-5,3},
- {-5,3},{-5,3},{-5,3},{-5,3},{-5,3},{-5,3},{-5,3},{-5,3},{-5,3},
- {-5,3},{-5,3},{-5,3},{-5,3},{-5,3},{4,3},{4,3},{4,3},{4,3},{4,3},
- {4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},
- {2,3},{2,3},{2,3},{2,3},{2,3},{2,3},{2,3},{2,3},{2,3},{2,3},{2,3},
- {2,3},{2,3},{2,3},{2,3},{2,3},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},
- {3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},
- {3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},
- {3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},
- {3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},
- {3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},
- {3,1},{3,1},{3,1},{-2,4},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},
- {-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},
- {-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-3,3}
-};
-
-/* Uncompressed decoding table. */
-static const cfd_node cf_uncompressed_decode[] = {
- {64,12},{5,6},{4,5},{4,5},{3,4},{3,4},{3,4},{3,4},{2,3},{2,3},
- {2,3},{2,3},{2,3},{2,3},{2,3},{2,3},{1,2},{1,2},{1,2},{1,2},{1,2},
- {1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},
- {0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},
- {0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},
- {0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},
- {-1,0},{-1,0},{8,6},{9,6},{6,5},{6,5},{7,5},{7,5},{4,4},{4,4},
- {4,4},{4,4},{5,4},{5,4},{5,4},{5,4},{2,3},{2,3},{2,3},{2,3},{2,3},
- {2,3},{2,3},{2,3},{3,3},{3,3},{3,3},{3,3},{3,3},{3,3},{3,3},{3,3},
- {0,2},{0,2},{0,2},{0,2},{0,2},{0,2},{0,2},{0,2},{0,2},{0,2},{0,2},
- {0,2},{0,2},{0,2},{0,2},{0,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},
- {1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2}
-};
-
-/* bit magic */
-
-static inline int getbit(const unsigned char *buf, int x)
-{
- return ( buf[x >> 3] >> ( 7 - (x & 7) ) ) & 1;
-}
-
-static const unsigned char mask[8] = {
- 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0
-};
-
-static const unsigned char clz[256] = {
- 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static inline int
-find_changing(const unsigned char *line, int x, int w)
-{
- int a, b, m, W;
-
- if (!line)
- return w;
-
- /* We assume w > 0, -1 <= x < w */
- if (x < 0)
- {
- x = 0;
- m = 0xFF;
- }
- else
- {
- /* Mask out the bits we've already used (including the one
- * we started from) */
- m = mask[x & 7];
- }
- /* We have 'w' pixels (bits) in line. The last pixel that can be
- * safely accessed is the (w-1)th bit of line.
- * By taking W = w>>3, we know that the first W bytes of line are
- * full, with w&7 stray bits following. */
- W = w>>3;
- x >>= 3;
- a = line[x]; /* Safe as x < w => x <= w-1 => x>>3 <= (w-1)>>3 */
- b = a ^ (a>>1);
- b &= m;
- if (x >= W)
- {
- /* Within the last byte already */
- x = (x<<3) + clz[b];
- if (x > w)
- x = w;
- return x;
- }
- while (b == 0)
- {
- if (++x >= W)
- goto nearend;
- b = a & 1;
- a = line[x];
- b = (b<<7) ^ a ^ (a>>1);
- }
- return (x<<3) + clz[b];
-nearend:
- /* We have less than a byte to go. If no stray bits, exit now. */
- if ((x<<3) == w)
- return w;
- b = a&1;
- a = line[x];
- b = (b<<7) ^ a ^ (a>>1);
- x = (x<<3) + clz[b];
- if (x > w)
- x = w;
- return x;
-}
-
-static inline int
-find_changing_color(const unsigned char *line, int x, int w, int color)
-{
- if (!line || x >= w)
- return w;
-
- x = find_changing(line, (x > 0 || !color) ? x : -1, w);
-
- if (x < w && getbit(line, x) != color)
- x = find_changing(line, x, w);
-
- return x;
-}
-
-static const unsigned char lm[8] = {
- 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01
-};
-
-static const unsigned char rm[8] = {
- 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE
-};
-
-static inline void setbits(unsigned char *line, int x0, int x1)
-{
- int a0, a1, b0, b1, a;
-
- if (x1 <= x0)
- return;
-
- a0 = x0 >> 3;
- a1 = x1 >> 3;
-
- b0 = x0 & 7;
- b1 = x1 & 7;
-
- if (a0 == a1)
- {
- if (b1)
- line[a0] |= lm[b0] & rm[b1];
- }
- else
- {
- line[a0] |= lm[b0];
- for (a = a0 + 1; a < a1; a++)
- line[a] = 0xFF;
- if (b1)
- line[a1] |= rm[b1];
- }
-}
-
-typedef struct fz_faxd_s fz_faxd;
-
-enum
-{
- STATE_NORMAL, /* neutral state, waiting for any code */
- STATE_MAKEUP, /* got a 1d makeup code, waiting for terminating code */
- STATE_EOL, /* at eol, needs output buffer space */
- STATE_H1, STATE_H2, /* in H part 1 and 2 (both makeup and terminating codes) */
- STATE_DONE /* all done */
-};
-
-struct fz_faxd_s
-{
- fz_context *ctx;
- 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;
-
- int stride;
- int ridx;
-
- int bidx;
- unsigned int word;
-
- int stage;
-
- int a, c, dim, eolc;
- unsigned char *ref;
- unsigned char *dst;
- unsigned char *rp, *wp;
-};
-
-static inline void eat_bits(fz_faxd *fax, int nbits)
-{
- fax->word <<= nbits;
- fax->bidx += nbits;
-}
-
-static int
-fill_bits(fz_faxd *fax)
-{
- while (fax->bidx >= 8)
- {
- int c = fz_read_byte(fax->chain);
- if (c == EOF)
- return EOF;
- fax->bidx -= 8;
- fax->word |= c << fax->bidx;
- }
- return 0;
-}
-
-static int
-get_code(fz_faxd *fax, const cfd_node *table, int initialbits)
-{
- unsigned int word = fax->word;
- int tidx = word >> (32 - initialbits);
- int val = table[tidx].val;
- int nbits = table[tidx].nbits;
-
- if (nbits > initialbits)
- {
- int mask = (1 << (32 - initialbits)) - 1;
- tidx = val + ((word & mask) >> (32 - nbits));
- val = table[tidx].val;
- nbits = initialbits + table[tidx].nbits;
- }
-
- eat_bits(fax, nbits);
-
- return val;
-}
-
-/* decode one 1d code */
-static void
-dec1d(fz_context *ctx, fz_faxd *fax)
-{
- int code;
-
- if (fax->a == -1)
- fax->a = 0;
-
- if (fax->c)
- code = get_code(fax, cf_black_decode, cfd_black_initial_bits);
- else
- code = get_code(fax, cf_white_decode, cfd_white_initial_bits);
-
- if (code == UNCOMPRESSED)
- fz_throw(ctx, FZ_ERROR_GENERIC, "uncompressed data in faxd");
-
- if (code < 0)
- fz_throw(ctx, FZ_ERROR_GENERIC, "negative code in 1d faxd");
-
- if (fax->a + code > fax->columns)
- fz_throw(ctx, FZ_ERROR_GENERIC, "overflow in 1d faxd");
-
- if (fax->c)
- setbits(fax->dst, fax->a, fax->a + code);
-
- fax->a += code;
-
- if (code < 64)
- {
- fax->c = !fax->c;
- fax->stage = STATE_NORMAL;
- }
- else
- fax->stage = STATE_MAKEUP;
-}
-
-/* decode one 2d code */
-static void
-dec2d(fz_context *ctx, fz_faxd *fax)
-{
- int code, b1, b2;
-
- if (fax->stage == STATE_H1 || fax->stage == STATE_H2)
- {
- if (fax->a == -1)
- fax->a = 0;
-
- if (fax->c)
- code = get_code(fax, cf_black_decode, cfd_black_initial_bits);
- else
- code = get_code(fax, cf_white_decode, cfd_white_initial_bits);
-
- if (code == UNCOMPRESSED)
- fz_throw(ctx, FZ_ERROR_GENERIC, "uncompressed data in faxd");
-
- if (code < 0)
- fz_throw(ctx, FZ_ERROR_GENERIC, "negative code in 2d faxd");
-
- if (fax->a + code > fax->columns)
- fz_throw(ctx, FZ_ERROR_GENERIC, "overflow in 2d faxd");
-
- if (fax->c)
- setbits(fax->dst, fax->a, fax->a + code);
-
- fax->a += code;
-
- if (code < 64)
- {
- fax->c = !fax->c;
- if (fax->stage == STATE_H1)
- fax->stage = STATE_H2;
- else if (fax->stage == STATE_H2)
- fax->stage = STATE_NORMAL;
- }
-
- return;
- }
-
- code = get_code(fax, cf_2d_decode, cfd_2d_initial_bits);
-
- switch (code)
- {
- case H:
- fax->stage = STATE_H1;
- break;
-
- case P:
- b1 = find_changing_color(fax->ref, fax->a, fax->columns, !fax->c);
- if (b1 >= fax->columns)
- b2 = fax->columns;
- else
- b2 = find_changing(fax->ref, b1, fax->columns);
- if (fax->c) setbits(fax->dst, fax->a, b2);
- fax->a = b2;
- break;
-
- case V0:
- b1 = find_changing_color(fax->ref, fax->a, fax->columns, !fax->c);
- if (fax->c) setbits(fax->dst, fax->a, b1);
- fax->a = b1;
- fax->c = !fax->c;
- break;
-
- case VR1:
- b1 = 1 + find_changing_color(fax->ref, fax->a, fax->columns, !fax->c);
- if (b1 >= fax->columns) b1 = fax->columns;
- if (fax->c) setbits(fax->dst, fax->a, b1);
- fax->a = b1;
- fax->c = !fax->c;
- break;
-
- case VR2:
- b1 = 2 + find_changing_color(fax->ref, fax->a, fax->columns, !fax->c);
- if (b1 >= fax->columns) b1 = fax->columns;
- if (fax->c) setbits(fax->dst, fax->a, b1);
- fax->a = b1;
- fax->c = !fax->c;
- break;
-
- case VR3:
- b1 = 3 + find_changing_color(fax->ref, fax->a, fax->columns, !fax->c);
- if (b1 >= fax->columns) b1 = fax->columns;
- if (fax->c) setbits(fax->dst, fax->a, b1);
- fax->a = b1;
- fax->c = !fax->c;
- break;
-
- case VL1:
- b1 = -1 + find_changing_color(fax->ref, fax->a, fax->columns, !fax->c);
- if (b1 < 0) b1 = 0;
- if (fax->c) setbits(fax->dst, fax->a, b1);
- fax->a = b1;
- fax->c = !fax->c;
- break;
-
- case VL2:
- b1 = -2 + find_changing_color(fax->ref, fax->a, fax->columns, !fax->c);
- if (b1 < 0) b1 = 0;
- if (fax->c) setbits(fax->dst, fax->a, b1);
- fax->a = b1;
- fax->c = !fax->c;
- break;
-
- case VL3:
- b1 = -3 + find_changing_color(fax->ref, fax->a, fax->columns, !fax->c);
- if (b1 < 0) b1 = 0;
- if (fax->c) setbits(fax->dst, fax->a, b1);
- fax->a = b1;
- fax->c = !fax->c;
- break;
-
- case UNCOMPRESSED:
- fz_throw(ctx, FZ_ERROR_GENERIC, "uncompressed data in faxd");
-
- case ERROR:
- fz_throw(ctx, FZ_ERROR_GENERIC, "invalid code in 2d faxd");
-
- default:
- fz_throw(ctx, FZ_ERROR_GENERIC, "invalid code in 2d faxd (%d)", code);
- }
-}
-
-static int
-read_faxd(fz_stream *stm, unsigned char *buf, int len)
-{
- fz_faxd *fax = stm->state;
- unsigned char *p = buf;
- unsigned char *ep = buf + len;
- unsigned char *tmp;
-
- if (fax->stage == STATE_DONE)
- return 0;
-
- if (fax->stage == STATE_EOL)
- goto eol;
-
-loop:
-
- if (fill_bits(fax))
- {
- if (fax->bidx > 31)
- {
- if (fax->a > 0)
- goto eol;
- goto rtc;
- }
- }
-
- if ((fax->word >> (32 - 12)) == 0)
- {
- eat_bits(fax, 1);
- goto loop;
- }
-
- if ((fax->word >> (32 - 12)) == 1)
- {
- eat_bits(fax, 12);
- fax->eolc ++;
-
- if (fax->k > 0)
- {
- if (fax->a == -1)
- fax->a = 0;
- if ((fax->word >> (32 - 1)) == 1)
- fax->dim = 1;
- else
- fax->dim = 2;
- eat_bits(fax, 1);
- }
- }
- else if (fax->k > 0 && fax->a == -1)
- {
- fax->a = 0;
- if ((fax->word >> (32 - 1)) == 1)
- fax->dim = 1;
- else
- fax->dim = 2;
- eat_bits(fax, 1);
- }
- else if (fax->dim == 1)
- {
- fax->eolc = 0;
- dec1d(stm->ctx, fax);
- }
- else if (fax->dim == 2)
- {
- fax->eolc = 0;
- dec2d(stm->ctx, fax);
- }
-
- /* no eol check after makeup codes nor in the middle of an H code */
- if (fax->stage == STATE_MAKEUP || fax->stage == STATE_H1 || fax->stage == STATE_H2)
- goto loop;
-
- /* check for eol conditions */
- if (fax->eolc || fax->a >= fax->columns)
- {
- if (fax->a > 0)
- goto eol;
- if (fax->eolc == (fax->k < 0 ? 2 : 6))
- goto rtc;
- }
-
- goto loop;
-
-eol:
- fax->stage = STATE_EOL;
-
- if (fax->black_is_1)
- {
- while (fax->rp < fax->wp && p < ep)
- *p++ = *fax->rp++;
- }
- else
- {
- while (fax->rp < fax->wp && p < ep)
- *p++ = *fax->rp++ ^ 0xff;
- }
-
- if (fax->rp < fax->wp)
- return p - buf;
-
- tmp = fax->ref;
- fax->ref = fax->dst;
- fax->dst = tmp;
- memset(fax->dst, 0, fax->stride);
-
- fax->rp = fax->dst;
- fax->wp = fax->dst + fax->stride;
-
- fax->stage = STATE_NORMAL;
- fax->c = 0;
- fax->a = -1;
- fax->ridx ++;
-
- if (!fax->end_of_block && fax->rows)
- {
- if (fax->ridx >= fax->rows)
- goto rtc;
- }
-
- /* we have not read dim from eol, make a guess */
- if (fax->k > 0 && !fax->eolc && fax->a == -1)
- {
- if (fax->ridx % fax->k == 0)
- fax->dim = 1;
- else
- fax->dim = 2;
- }
-
- /* if end_of_line & encoded_byte_align, EOLs are *not* optional */
- if (fax->encoded_byte_align)
- {
- if (fax->end_of_line)
- eat_bits(fax, (12 - fax->bidx) & 7);
- else
- eat_bits(fax, (8 - fax->bidx) & 7);
- }
-
- /* no more space in output, don't decode the next row yet */
- if (p == buf + len)
- return p - buf;
-
- goto loop;
-
-rtc:
- fax->stage = STATE_DONE;
- return p - buf;
-}
-
-static void
-close_faxd(fz_context *ctx, void *state_)
-{
- fz_faxd *fax = (fz_faxd *)state_;
- int i;
-
- /* if we read any extra bytes, try to put them back */
- i = (32 - fax->bidx) / 8;
- while (i--)
- fz_unread_byte(fax->chain);
-
- fz_close(fax->chain);
- fz_free(ctx, fax->ref);
- fz_free(ctx, fax->dst);
- fz_free(ctx, fax);
-}
-
-/* Default: columns = 1728, end_of_block = 1, the rest = 0 */
-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_context *ctx = chain->ctx;
- fz_faxd *fax = NULL;
-
- fz_var(fax);
-
- fz_try(ctx)
- {
- fax = fz_malloc_struct(ctx, fz_faxd);
- fax->chain = chain;
-
- fax->ref = NULL;
- fax->dst = NULL;
-
- fax->k = k;
- fax->end_of_line = end_of_line;
- fax->encoded_byte_align = encoded_byte_align;
- fax->columns = columns;
- fax->rows = rows;
- fax->end_of_block = end_of_block;
- fax->black_is_1 = black_is_1;
-
- fax->stride = ((fax->columns - 1) >> 3) + 1;
- fax->ridx = 0;
- fax->bidx = 32;
- fax->word = 0;
-
- fax->stage = STATE_NORMAL;
- fax->a = -1;
- fax->c = 0;
- fax->dim = fax->k < 0 ? 2 : 1;
- fax->eolc = 0;
-
- fax->ref = fz_malloc(ctx, fax->stride);
- fax->dst = fz_malloc(ctx, fax->stride);
- fax->rp = fax->dst;
- fax->wp = fax->dst + fax->stride;
-
- memset(fax->ref, 0, fax->stride);
- memset(fax->dst, 0, fax->stride);
- }
- fz_catch(ctx)
- {
- if (fax)
- {
- fz_free(ctx, fax->dst);
- fz_free(ctx, fax->ref);
- }
- fz_free(ctx, fax);
- fz_close(chain);
- fz_rethrow(ctx);
- }
-
- return fz_new_stream(ctx, fax, read_faxd, close_faxd);
-}
diff --git a/fitz/filt_flate.c b/fitz/filt_flate.c
deleted file mode 100644
index 73451d59..00000000
--- a/fitz/filt_flate.c
+++ /dev/null
@@ -1,117 +0,0 @@
-#include "mupdf/fitz.h"
-
-#include <zlib.h>
-
-typedef struct fz_flate_s fz_flate;
-
-struct fz_flate_s
-{
- fz_stream *chain;
- z_stream z;
-};
-
-static void *zalloc(void *opaque, unsigned int items, unsigned int size)
-{
- return fz_malloc_array_no_throw(opaque, items, size);
-}
-
-static void zfree(void *opaque, void *ptr)
-{
- fz_free(opaque, ptr);
-}
-
-static int
-read_flated(fz_stream *stm, unsigned char *outbuf, int outlen)
-{
- fz_flate *state = stm->state;
- fz_stream *chain = state->chain;
- z_streamp zp = &state->z;
- int code;
-
- zp->next_out = outbuf;
- zp->avail_out = outlen;
-
- while (zp->avail_out > 0)
- {
- if (chain->rp == chain->wp)
- fz_fill_buffer(chain);
-
- zp->next_in = chain->rp;
- zp->avail_in = chain->wp - chain->rp;
-
- code = inflate(zp, Z_SYNC_FLUSH);
-
- chain->rp = chain->wp - zp->avail_in;
-
- if (code == Z_STREAM_END)
- {
- return outlen - zp->avail_out;
- }
- else if (code == Z_BUF_ERROR)
- {
- fz_warn(stm->ctx, "premature end of data in flate filter");
- return outlen - zp->avail_out;
- }
- else if (code == Z_DATA_ERROR && zp->avail_in == 0)
- {
- fz_warn(stm->ctx, "ignoring zlib error: %s", zp->msg);
- return outlen - zp->avail_out;
- }
- else if (code != Z_OK)
- {
- fz_throw(stm->ctx, FZ_ERROR_GENERIC, "zlib error: %s", zp->msg);
- }
- }
-
- return outlen - zp->avail_out;
-}
-
-static void
-close_flated(fz_context *ctx, void *state_)
-{
- fz_flate *state = (fz_flate *)state_;
- int code;
-
- code = inflateEnd(&state->z);
- if (code != Z_OK)
- fz_warn(ctx, "zlib error: inflateEnd: %s", state->z.msg);
-
- fz_close(state->chain);
- fz_free(ctx, state);
-}
-
-fz_stream *
-fz_open_flated(fz_stream *chain)
-{
- fz_flate *state = NULL;
- int code = Z_OK;
- fz_context *ctx = chain->ctx;
-
- fz_var(code);
- fz_var(state);
-
- fz_try(ctx)
- {
- state = fz_malloc_struct(ctx, fz_flate);
- state->chain = chain;
-
- state->z.zalloc = zalloc;
- state->z.zfree = zfree;
- state->z.opaque = ctx;
- state->z.next_in = NULL;
- state->z.avail_in = 0;
-
- code = inflateInit(&state->z);
- if (code != Z_OK)
- fz_throw(ctx, FZ_ERROR_GENERIC, "zlib error: inflateInit: %s", state->z.msg);
- }
- fz_catch(ctx)
- {
- if (state && code == Z_OK)
- inflateEnd(&state->z);
- fz_free(ctx, state);
- fz_close(chain);
- fz_rethrow(ctx);
- }
- return fz_new_stream(ctx, state, read_flated, close_flated);
-}
diff --git a/fitz/filt_jbig2d.c b/fitz/filt_jbig2d.c
deleted file mode 100644
index 12eb8c3b..00000000
--- a/fitz/filt_jbig2d.c
+++ /dev/null
@@ -1,108 +0,0 @@
-#include "mupdf/fitz.h"
-
-#include <jbig2.h>
-
-typedef struct fz_jbig2d_s fz_jbig2d;
-
-struct fz_jbig2d_s
-{
- fz_stream *chain;
- Jbig2Ctx *ctx;
- Jbig2GlobalCtx *gctx;
- Jbig2Image *page;
- int idx;
-};
-
-static void
-close_jbig2d(fz_context *ctx, void *state_)
-{
- fz_jbig2d *state = (fz_jbig2d *)state_;
- if (state->page)
- jbig2_release_page(state->ctx, state->page);
- if (state->gctx)
- jbig2_global_ctx_free(state->gctx);
- jbig2_ctx_free(state->ctx);
- fz_close(state->chain);
- fz_free(ctx, state);
-}
-
-static int
-read_jbig2d(fz_stream *stm, unsigned char *buf, int len)
-{
- fz_jbig2d *state = stm->state;
- unsigned char tmp[4096];
- unsigned char *p = buf;
- unsigned char *ep = buf + len;
- unsigned char *s;
- int x, w, n;
-
- if (!state->page)
- {
- while (1)
- {
- n = fz_read(state->chain, tmp, sizeof tmp);
- if (n == 0)
- break;
- jbig2_data_in(state->ctx, tmp, n);
- }
-
- jbig2_complete_page(state->ctx);
-
- state->page = jbig2_page_out(state->ctx);
- if (!state->page)
- fz_throw(stm->ctx, FZ_ERROR_GENERIC, "jbig2_page_out failed");
- }
-
- s = state->page->data;
- w = state->page->height * state->page->stride;
- x = state->idx;
- while (p < ep && x < w)
- *p++ = s[x++] ^ 0xff;
- state->idx = x;
-
- return p - buf;
-}
-
-fz_stream *
-fz_open_jbig2d(fz_stream *chain, fz_buffer *globals)
-{
- fz_jbig2d *state = NULL;
- fz_context *ctx = chain->ctx;
-
- fz_var(state);
-
- fz_try(ctx)
- {
- state = fz_malloc_struct(chain->ctx, fz_jbig2d);
- state->ctx = NULL;
- state->gctx = NULL;
- state->chain = chain;
- state->ctx = jbig2_ctx_new(NULL, JBIG2_OPTIONS_EMBEDDED, NULL, NULL, NULL);
- state->page = NULL;
- state->idx = 0;
-
- if (globals)
- {
- jbig2_data_in(state->ctx, globals->data, globals->len);
- state->gctx = jbig2_make_global_ctx(state->ctx);
- state->ctx = jbig2_ctx_new(NULL, JBIG2_OPTIONS_EMBEDDED, state->gctx, NULL, NULL);
- }
- }
- fz_catch(ctx)
- {
- if (state)
- {
- if (state->gctx)
- jbig2_global_ctx_free(state->gctx);
- if (state->ctx)
- jbig2_ctx_free(state->ctx);
- }
- fz_drop_buffer(ctx, globals);
- fz_free(ctx, state);
- fz_close(chain);
- fz_rethrow(ctx);
- }
- fz_drop_buffer(ctx, globals);
-
- return fz_new_stream(ctx, state, read_jbig2d, close_jbig2d);
-}
diff --git a/fitz/filt_lzwd.c b/fitz/filt_lzwd.c
deleted file mode 100644
index 73909ca1..00000000
--- a/fitz/filt_lzwd.c
+++ /dev/null
@@ -1,224 +0,0 @@
-#include "mupdf/fitz.h"
-
-/* TODO: error checking */
-
-enum
-{
- MIN_BITS = 9,
- MAX_BITS = 12,
- NUM_CODES = (1 << MAX_BITS),
- LZW_CLEAR = 256,
- LZW_EOD = 257,
- LZW_FIRST = 258,
- MAX_LENGTH = 4097
-};
-
-typedef struct lzw_code_s lzw_code;
-
-struct lzw_code_s
-{
- int prev; /* prev code (in string) */
- unsigned short length; /* string len, including this token */
- unsigned char value; /* data value */
- unsigned char first_char; /* first token of string */
-};
-
-typedef struct fz_lzwd_s fz_lzwd;
-
-struct fz_lzwd_s
-{
- fz_stream *chain;
- int eod;
-
- int early_change;
-
- int code_bits; /* num bits/code */
- int code; /* current code */
- int old_code; /* previously recognized code */
- int next_code; /* next free entry */
-
- lzw_code table[NUM_CODES];
-
- unsigned char bp[MAX_LENGTH];
- unsigned char *rp, *wp;
-};
-
-static int
-read_lzwd(fz_stream *stm, unsigned char *buf, int len)
-{
- fz_lzwd *lzw = stm->state;
- lzw_code *table = lzw->table;
- unsigned char *p = buf;
- unsigned char *ep = buf + len;
- unsigned char *s;
- int codelen;
-
- int code_bits = lzw->code_bits;
- int code = lzw->code;
- int old_code = lzw->old_code;
- int next_code = lzw->next_code;
-
- while (lzw->rp < lzw->wp && p < ep)
- *p++ = *lzw->rp++;
-
- while (p < ep)
- {
- if (lzw->eod)
- return 0;
-
- code = fz_read_bits(lzw->chain, code_bits);
-
- if (fz_is_eof_bits(lzw->chain))
- {
- lzw->eod = 1;
- break;
- }
-
- if (code == LZW_EOD)
- {
- lzw->eod = 1;
- break;
- }
-
- if (next_code >= NUM_CODES && code != LZW_CLEAR)
- {
- fz_warn(stm->ctx, "missing clear code in lzw decode");
- code = LZW_CLEAR;
- }
-
- if (code == LZW_CLEAR)
- {
- code_bits = MIN_BITS;
- next_code = LZW_FIRST;
- old_code = -1;
- continue;
- }
-
- /* if stream starts without a clear code, old_code is undefined... */
- if (old_code == -1)
- {
- old_code = code;
- }
- else if (code > next_code || next_code >= NUM_CODES)
- {
- fz_warn(stm->ctx, "out of range code encountered in lzw decode");
- }
- else
- {
- /* add new entry to the code table */
- table[next_code].prev = old_code;
- table[next_code].first_char = table[old_code].first_char;
- table[next_code].length = table[old_code].length + 1;
- if (code < next_code)
- table[next_code].value = table[code].first_char;
- else if (code == next_code)
- table[next_code].value = table[next_code].first_char;
- else
- fz_warn(stm->ctx, "out of range code encountered in lzw decode");
-
- next_code ++;
-
- if (next_code > (1 << code_bits) - lzw->early_change - 1)
- {
- code_bits ++;
- if (code_bits > MAX_BITS)
- code_bits = MAX_BITS;
- }
-
- old_code = code;
- }
-
- /* code maps to a string, copy to output (in reverse...) */
- if (code > 255)
- {
- codelen = table[code].length;
- lzw->rp = lzw->bp;
- lzw->wp = lzw->bp + codelen;
-
- assert(codelen < MAX_LENGTH);
-
- s = lzw->wp;
- do {
- *(--s) = table[code].value;
- code = table[code].prev;
- } while (code >= 0 && s > lzw->bp);
- }
-
- /* ... or just a single character */
- else
- {
- lzw->bp[0] = code;
- lzw->rp = lzw->bp;
- lzw->wp = lzw->bp + 1;
- }
-
- /* copy to output */
- while (lzw->rp < lzw->wp && p < ep)
- *p++ = *lzw->rp++;
- }
-
- lzw->code_bits = code_bits;
- lzw->code = code;
- lzw->old_code = old_code;
- lzw->next_code = next_code;
-
- return p - buf;
-}
-
-static void
-close_lzwd(fz_context *ctx, void *state_)
-{
- fz_lzwd *lzw = (fz_lzwd *)state_;
- fz_close(lzw->chain);
- fz_free(ctx, lzw);
-}
-
-/* Default: early_change = 1 */
-fz_stream *
-fz_open_lzwd(fz_stream *chain, int early_change)
-{
- fz_context *ctx = chain->ctx;
- fz_lzwd *lzw = NULL;
- int i;
-
- fz_var(lzw);
-
- fz_try(ctx)
- {
- lzw = fz_malloc_struct(ctx, fz_lzwd);
- lzw->chain = chain;
- lzw->eod = 0;
- lzw->early_change = early_change;
-
- for (i = 0; i < 256; i++)
- {
- lzw->table[i].value = i;
- lzw->table[i].first_char = i;
- lzw->table[i].length = 1;
- lzw->table[i].prev = -1;
- }
-
- for (i = 256; i < NUM_CODES; i++)
- {
- lzw->table[i].value = 0;
- lzw->table[i].first_char = 0;
- lzw->table[i].length = 0;
- lzw->table[i].prev = -1;
- }
-
- lzw->code_bits = MIN_BITS;
- lzw->code = -1;
- lzw->next_code = LZW_FIRST;
- lzw->old_code = -1;
- lzw->rp = lzw->bp;
- lzw->wp = lzw->bp;
- }
- fz_catch(ctx)
- {
- fz_free(ctx, lzw);
- fz_close(chain);
- fz_rethrow(ctx);
- }
-
- return fz_new_stream(ctx, lzw, read_lzwd, close_lzwd);
-}
diff --git a/fitz/filt_predict.c b/fitz/filt_predict.c
deleted file mode 100644
index c8de290a..00000000
--- a/fitz/filt_predict.c
+++ /dev/null
@@ -1,256 +0,0 @@
-#include "mupdf/fitz.h"
-
-/* TODO: check if this works with 16bpp images */
-
-enum { MAXC = 32 };
-
-typedef struct fz_predict_s fz_predict;
-
-struct fz_predict_s
-{
- fz_stream *chain;
-
- int predictor;
- int columns;
- int colors;
- int bpc;
-
- int stride;
- int bpp;
- unsigned char *in;
- unsigned char *out;
- unsigned char *ref;
- unsigned char *rp, *wp;
-};
-
-static inline int getcomponent(unsigned char *line, int x, int bpc)
-{
- switch (bpc)
- {
- case 1: return (line[x >> 3] >> ( 7 - (x & 7) ) ) & 1;
- case 2: return (line[x >> 2] >> ( ( 3 - (x & 3) ) << 1 ) ) & 3;
- case 4: return (line[x >> 1] >> ( ( 1 - (x & 1) ) << 2 ) ) & 15;
- case 8: return line[x];
- case 16: return (line[x<<1]<<8)+line[(x<<1)+1];
- }
- return 0;
-}
-
-static inline void putcomponent(unsigned char *buf, int x, int bpc, int value)
-{
- switch (bpc)
- {
- case 1: buf[x >> 3] |= value << (7 - (x & 7)); break;
- case 2: buf[x >> 2] |= value << ((3 - (x & 3)) << 1); break;
- case 4: buf[x >> 1] |= value << ((1 - (x & 1)) << 2); break;
- case 8: buf[x] = value; break;
- case 16: buf[x<<1] = value>>8; buf[(x<<1)+1] = value; break;
- }
-}
-
-static inline int paeth(int a, int b, int c)
-{
- /* The definitions of ac and bc are correct, not a typo. */
- int ac = b - c, bc = a - c, abcc = ac + bc;
- int pa = fz_absi(ac);
- int pb = fz_absi(bc);
- int pc = fz_absi(abcc);
- return pa <= pb && pa <= pc ? a : pb <= pc ? b : c;
-}
-
-static void
-fz_predict_tiff(fz_predict *state, unsigned char *out, unsigned char *in, int len)
-{
- int left[MAXC];
- int i, k;
- const int mask = (1 << state->bpc)-1;
-
- for (k = 0; k < state->colors; k++)
- left[k] = 0;
- memset(out, 0, state->stride);
-
- for (i = 0; i < state->columns; i++)
- {
- for (k = 0; k < state->colors; k++)
- {
- int a = getcomponent(in, i * state->colors + k, state->bpc);
- int b = a + left[k];
- int c = b & mask;
- putcomponent(out, i * state->colors + k, state->bpc, c);
- left[k] = c;
- }
- }
-}
-
-static void
-fz_predict_png(fz_predict *state, unsigned char *out, unsigned char *in, int len, int predictor)
-{
- int bpp = state->bpp;
- int i;
- unsigned char *ref = state->ref;
-
- switch (predictor)
- {
- case 0:
- memcpy(out, in, len);
- break;
- case 1:
- for (i = bpp; i > 0; i--)
- {
- *out++ = *in++;
- }
- for (i = len - bpp; i > 0; i--)
- {
- *out = *in++ + out[-bpp];
- out++;
- }
- break;
- case 2:
- for (i = bpp; i > 0; i--)
- {
- *out++ = *in++ + *ref++;
- }
- for (i = len - bpp; i > 0; i--)
- {
- *out++ = *in++ + *ref++;
- }
- break;
- case 3:
- for (i = bpp; i > 0; i--)
- {
- *out++ = *in++ + (*ref++) / 2;
- }
- for (i = len - bpp; i > 0; i--)
- {
- *out = *in++ + (out[-bpp] + *ref++) / 2;
- out++;
- }
- break;
- case 4:
- for (i = bpp; i > 0; i--)
- {
- *out++ = *in++ + paeth(0, *ref++, 0);
- }
- for (i = len - bpp; i > 0; i --)
- {
- *out = *in++ + paeth(out[-bpp], *ref, ref[-bpp]);
- ref++;
- out++;
- }
- break;
- }
-}
-
-static int
-read_predict(fz_stream *stm, unsigned char *buf, int len)
-{
- fz_predict *state = stm->state;
- unsigned char *p = buf;
- unsigned char *ep = buf + len;
- int ispng = state->predictor >= 10;
- int n;
-
- while (state->rp < state->wp && p < ep)
- *p++ = *state->rp++;
-
- while (p < ep)
- {
- n = fz_read(state->chain, state->in, state->stride + ispng);
- if (n == 0)
- return p - buf;
-
- if (state->predictor == 1)
- memcpy(state->out, state->in, n);
- else if (state->predictor == 2)
- fz_predict_tiff(state, state->out, state->in, n);
- else
- {
- fz_predict_png(state, state->out, state->in + 1, n - 1, state->in[0]);
- memcpy(state->ref, state->out, state->stride);
- }
-
- state->rp = state->out;
- state->wp = state->out + n - ispng;
-
- while (state->rp < state->wp && p < ep)
- *p++ = *state->rp++;
- }
-
- return p - buf;
-}
-
-static void
-close_predict(fz_context *ctx, void *state_)
-{
- fz_predict *state = (fz_predict *)state_;
- fz_close(state->chain);
- fz_free(ctx, state->in);
- fz_free(ctx, state->out);
- fz_free(ctx, state->ref);
- fz_free(ctx, state);
-}
-
-/* Default values: predictor = 1, columns = 1, colors = 1, bpc = 8 */
-fz_stream *
-fz_open_predict(fz_stream *chain, int predictor, int columns, int colors, int bpc)
-{
- fz_context *ctx = chain->ctx;
- fz_predict *state = NULL;
-
- fz_var(state);
-
- if (predictor < 1)
- predictor = 1;
- if (columns < 1)
- columns = 1;
- if (colors < 1)
- colors = 1;
- if (bpc < 1)
- bpc = 8;
-
- fz_try(ctx)
- {
- state = fz_malloc_struct(ctx, fz_predict);
- state->in = NULL;
- state->out = NULL;
- state->chain = chain;
-
- state->predictor = predictor;
- state->columns = columns;
- state->colors = colors;
- state->bpc = bpc;
-
- if (state->predictor != 1 && state->predictor != 2 &&
- state->predictor != 10 && state->predictor != 11 &&
- state->predictor != 12 && state->predictor != 13 &&
- state->predictor != 14 && state->predictor != 15)
- {
- fz_warn(ctx, "invalid predictor: %d", state->predictor);
- state->predictor = 1;
- }
-
- state->stride = (state->bpc * state->colors * state->columns + 7) / 8;
- state->bpp = (state->bpc * state->colors + 7) / 8;
-
- state->in = fz_malloc(ctx, state->stride + 1);
- state->out = fz_malloc(ctx, state->stride);
- state->ref = fz_malloc(ctx, state->stride);
- state->rp = state->out;
- state->wp = state->out;
-
- memset(state->ref, 0, state->stride);
- }
- fz_catch(ctx)
- {
- if (state)
- {
- fz_free(ctx, state->in);
- fz_free(ctx, state->out);
- }
- fz_free(ctx, state);
- fz_close(chain);
- fz_rethrow(ctx);
- }
-
- return fz_new_stream(ctx, state, read_predict, close_predict);
-}
diff --git a/fitz/image_jpeg.c b/fitz/image_jpeg.c
deleted file mode 100644
index b968c0cf..00000000
--- a/fitz/image_jpeg.c
+++ /dev/null
@@ -1,111 +0,0 @@
-#include "mupdf/fitz.h"
-
-#include <jpeglib.h>
-
-static void error_exit(j_common_ptr cinfo)
-{
- char msg[JMSG_LENGTH_MAX];
- fz_context *ctx = (fz_context *)cinfo->client_data;
-
- cinfo->err->format_message(cinfo, msg);
- fz_throw(ctx, FZ_ERROR_GENERIC, "jpeg error: %s", msg);
-}
-
-static void init_source(j_decompress_ptr cinfo)
-{
- /* nothing to do */
-}
-
-static void term_source(j_decompress_ptr cinfo)
-{
- /* nothing to do */
-}
-
-static boolean fill_input_buffer(j_decompress_ptr cinfo)
-{
- static unsigned char eoi[2] = { 0xFF, JPEG_EOI };
- struct jpeg_source_mgr *src = cinfo->src;
- src->next_input_byte = eoi;
- src->bytes_in_buffer = 2;
- return 1;
-}
-
-static void skip_input_data(j_decompress_ptr cinfo, long num_bytes)
-{
- struct jpeg_source_mgr *src = cinfo->src;
- if (num_bytes > 0)
- {
- size_t skip = (size_t)num_bytes; /* size_t may be 64bit */
- if (skip > src->bytes_in_buffer)
- skip = (size_t)src->bytes_in_buffer;
- src->next_input_byte += skip;
- src->bytes_in_buffer -= skip;
- }
-}
-
-void
-fz_load_jpeg_info(fz_context *ctx, unsigned char *rbuf, int rlen, int *xp, int *yp, int *xresp, int *yresp, fz_colorspace **cspacep)
-{
- struct jpeg_decompress_struct cinfo;
- struct jpeg_error_mgr err;
- struct jpeg_source_mgr src;
-
- fz_try(ctx)
- {
- cinfo.client_data = ctx;
- cinfo.err = jpeg_std_error(&err);
- err.error_exit = error_exit;
-
- jpeg_create_decompress(&cinfo);
-
- cinfo.src = &src;
- src.init_source = init_source;
- src.fill_input_buffer = fill_input_buffer;
- src.skip_input_data = skip_input_data;
- src.resync_to_restart = jpeg_resync_to_restart;
- src.term_source = term_source;
- src.next_input_byte = rbuf;
- src.bytes_in_buffer = rlen;
-
- jpeg_read_header(&cinfo, 1);
-
- if (cinfo.num_components == 1)
- *cspacep = fz_device_gray(ctx);
- else if (cinfo.num_components == 3)
- *cspacep = fz_device_rgb(ctx);
- else if (cinfo.num_components == 4)
- *cspacep = fz_device_cmyk(ctx);
- else
- fz_throw(ctx, FZ_ERROR_GENERIC, "bad number of components in jpeg: %d", cinfo.num_components);
-
- *xp = cinfo.image_width;
- *yp = cinfo.image_height;
-
- if (cinfo.density_unit == 1)
- {
- *xresp = cinfo.X_density;
- *yresp = cinfo.Y_density;
- }
- else if (cinfo.density_unit == 2)
- {
- *xresp = cinfo.X_density * 254 / 100;
- *yresp = cinfo.Y_density * 254 / 100;
- }
- else
- {
- *xresp = 0;
- *yresp = 0;
- }
-
- if (*xresp <= 0) *xresp = 72;
- if (*yresp <= 0) *yresp = 72;
- }
- fz_always(ctx)
- {
- jpeg_destroy_decompress(&cinfo);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
-}
diff --git a/fitz/image_jpx.c b/fitz/image_jpx.c
deleted file mode 100644
index cd41277d..00000000
--- a/fitz/image_jpx.c
+++ /dev/null
@@ -1,253 +0,0 @@
-#include "mupdf/fitz.h"
-
-/* Without the definition of OPJ_STATIC, compilation fails on windows
- * due to the use of __stdcall. We believe it is required on some
- * linux toolchains too. */
-#define OPJ_STATIC
-#ifndef _MSC_VER
-#define OPJ_HAVE_STDINT_H
-#endif
-
-#include <openjpeg.h>
-
-static void fz_opj_error_callback(const char *msg, void *client_data)
-{
- fz_context *ctx = (fz_context *)client_data;
- fz_warn(ctx, "openjpeg error: %s", msg);
-}
-
-static void fz_opj_warning_callback(const char *msg, void *client_data)
-{
- fz_context *ctx = (fz_context *)client_data;
- fz_warn(ctx, "openjpeg warning: %s", msg);
-}
-
-static void fz_opj_info_callback(const char *msg, void *client_data)
-{
- /* fz_warn("openjpeg info: %s", msg); */
-}
-
-typedef struct stream_block_s
-{
- unsigned char *data;
- int size;
- int pos;
-} stream_block;
-
-OPJ_SIZE_T stream_read(void * p_buffer, OPJ_SIZE_T p_nb_bytes, void * p_user_data)
-{
- stream_block *sb = (stream_block *)p_user_data;
- int len;
-
- len = sb->size - sb->pos;
- if (len < 0)
- len = 0;
- if (len == 0)
- return (OPJ_SIZE_T)-1; /* End of file! */
- if ((OPJ_SIZE_T)len > p_nb_bytes)
- len = p_nb_bytes;
- memcpy(p_buffer, sb->data + sb->pos, len);
- sb->pos += len;
- return len;
-}
-
-OPJ_OFF_T stream_skip(OPJ_OFF_T skip, void * p_user_data)
-{
- stream_block *sb = (stream_block *)p_user_data;
-
- if (skip > sb->size - sb->pos)
- skip = sb->size - sb->pos;
- sb->pos += skip;
- return sb->pos;
-}
-
-OPJ_BOOL stream_seek(OPJ_OFF_T seek_pos, void * p_user_data)
-{
- stream_block *sb = (stream_block *)p_user_data;
-
- if (seek_pos > sb->size)
- return OPJ_FALSE;
- sb->pos = seek_pos;
- return OPJ_TRUE;
-}
-
-fz_pixmap *
-fz_load_jpx(fz_context *ctx, unsigned char *data, int size, fz_colorspace *defcs, int indexed)
-{
- fz_pixmap *img;
- fz_colorspace *origcs;
- opj_dparameters_t params;
- opj_codec_t *codec;
- opj_image_t *jpx;
- opj_stream_t *stream;
- fz_colorspace *colorspace;
- unsigned char *p;
- OPJ_CODEC_FORMAT format;
- int a, n, w, h, depth, sgnd;
- int x, y, k, v;
- stream_block sb;
-
- if (size < 2)
- fz_throw(ctx, FZ_ERROR_GENERIC, "not enough data to determine image format");
-
- /* Check for SOC marker -- if found we have a bare J2K stream */
- if (data[0] == 0xFF && data[1] == 0x4F)
- format = OPJ_CODEC_J2K;
- else
- format = OPJ_CODEC_JP2;
-
- opj_set_default_decoder_parameters(&params);
- if (indexed)
- params.flags |= OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG;
-
- codec = opj_create_decompress(format);
- opj_set_info_handler(codec, fz_opj_info_callback, ctx);
- opj_set_warning_handler(codec, fz_opj_warning_callback, ctx);
- opj_set_error_handler(codec, fz_opj_error_callback, ctx);
- if (!opj_setup_decoder(codec, &params))
- {
- fz_throw(ctx, FZ_ERROR_GENERIC, "j2k decode failed");
- }
-
- stream = opj_stream_default_create(OPJ_TRUE);
- sb.data = data;
- sb.pos = 0;
- sb.size = size;
-
- opj_stream_set_read_function(stream, stream_read);
- opj_stream_set_skip_function(stream, stream_skip);
- opj_stream_set_seek_function(stream, stream_seek);
- opj_stream_set_user_data(stream, &sb);
- /* Set the length to avoid an assert */
- opj_stream_set_user_data_length(stream, size);
-
- if (!opj_read_header(stream, codec, &jpx))
- {
- opj_stream_destroy(stream);
- opj_destroy_codec(codec);
- fz_throw(ctx, FZ_ERROR_GENERIC, "Failed to read JPX header");
- }
-
- if (!opj_decode(codec, stream, jpx))
- {
- opj_stream_destroy(stream);
- opj_destroy_codec(codec);
- opj_image_destroy(jpx);
- fz_throw(ctx, FZ_ERROR_GENERIC, "Failed to decode JPX image");
- }
-
- opj_stream_destroy(stream);
- opj_destroy_codec(codec);
-
- /* jpx should never be NULL here, but check anyway */
- if (!jpx)
- fz_throw(ctx, FZ_ERROR_GENERIC, "opj_decode failed");
-
- for (k = 1; k < (int)jpx->numcomps; k++)
- {
- if (jpx->comps[k].w != jpx->comps[0].w)
- {
- opj_image_destroy(jpx);
- fz_throw(ctx, FZ_ERROR_GENERIC, "image components have different width");
- }
- if (jpx->comps[k].h != jpx->comps[0].h)
- {
- opj_image_destroy(jpx);
- fz_throw(ctx, FZ_ERROR_GENERIC, "image components have different height");
- }
- if (jpx->comps[k].prec != jpx->comps[0].prec)
- {
- opj_image_destroy(jpx);
- fz_throw(ctx, FZ_ERROR_GENERIC, "image components have different precision");
- }
- }
-
- n = jpx->numcomps;
- w = jpx->comps[0].w;
- h = jpx->comps[0].h;
- depth = jpx->comps[0].prec;
- sgnd = jpx->comps[0].sgnd;
-
- if (jpx->color_space == OPJ_CLRSPC_SRGB && n == 4) { n = 3; a = 1; }
- else if (jpx->color_space == OPJ_CLRSPC_SYCC && n == 4) { n = 3; a = 1; }
- else if (n == 2) { n = 1; a = 1; }
- else if (n > 4) { n = 4; a = 1; }
- else { a = 0; }
-
- origcs = defcs;
- if (defcs)
- {
- if (defcs->n == n)
- {
- colorspace = defcs;
- }
- else
- {
- fz_warn(ctx, "jpx file and dict colorspaces do not match");
- defcs = NULL;
- }
- }
-
- if (!defcs)
- {
- switch (n)
- {
- case 1: colorspace = fz_device_gray(ctx); break;
- case 3: colorspace = fz_device_rgb(ctx); break;
- case 4: colorspace = fz_device_cmyk(ctx); break;
- }
- }
-
- fz_try(ctx)
- {
- img = fz_new_pixmap(ctx, colorspace, w, h);
- }
- fz_catch(ctx)
- {
- opj_image_destroy(jpx);
- fz_rethrow_message(ctx, "out of memory loading jpx");
- }
-
- p = img->samples;
- for (y = 0; y < h; y++)
- {
- for (x = 0; x < w; x++)
- {
- for (k = 0; k < n + a; k++)
- {
- v = jpx->comps[k].data[y * w + x];
- if (sgnd)
- v = v + (1 << (depth - 1));
- if (depth > 8)
- v = v >> (depth - 8);
- *p++ = v;
- }
- if (!a)
- *p++ = 255;
- }
- }
-
- opj_image_destroy(jpx);
-
- if (a)
- {
- if (n == 4)
- {
- fz_pixmap *tmp = fz_new_pixmap(ctx, fz_device_rgb(ctx), w, h);
- fz_convert_pixmap(ctx, tmp, img);
- fz_drop_pixmap(ctx, img);
- img = tmp;
- }
- fz_premultiply_pixmap(ctx, img);
- }
-
- if (origcs != defcs)
- {
- fz_pixmap *tmp = fz_new_pixmap(ctx, origcs, w, h);
- fz_convert_pixmap(ctx, tmp, img);
- fz_drop_pixmap(ctx, img);
- img = tmp;
- }
-
- return img;
-}
diff --git a/fitz/image_png.c b/fitz/image_png.c
deleted file mode 100644
index ad22e128..00000000
--- a/fitz/image_png.c
+++ /dev/null
@@ -1,599 +0,0 @@
-#include "mupdf/fitz.h"
-
-#include <zlib.h>
-
-struct info
-{
- fz_context *ctx;
- unsigned int width, height, depth, n;
- int interlace, indexed;
- unsigned int size;
- unsigned char *samples;
- unsigned char palette[256*4];
- int transparency;
- int trns[3];
- int xres, yres;
-};
-
-static inline unsigned int getuint(unsigned char *p)
-{
- return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
-}
-
-static inline int getcomp(unsigned char *line, int x, int bpc)
-{
- switch (bpc)
- {
- case 1: return (line[x >> 3] >> ( 7 - (x & 7) ) ) & 1;
- case 2: return (line[x >> 2] >> ( ( 3 - (x & 3) ) << 1 ) ) & 3;
- case 4: return (line[x >> 1] >> ( ( 1 - (x & 1) ) << 2 ) ) & 15;
- case 8: return line[x];
- case 16: return line[x << 1] << 8 | line[(x << 1) + 1];
- }
- return 0;
-}
-
-static inline void putcomp(unsigned char *line, int x, int bpc, int value)
-{
- int maxval = (1 << bpc) - 1;
-
- switch (bpc)
- {
- case 1: line[x >> 3] &= ~(maxval << (7 - (x & 7))); break;
- case 2: line[x >> 2] &= ~(maxval << ((3 - (x & 3)) << 1)); break;
- case 4: line[x >> 1] &= ~(maxval << ((1 - (x & 1)) << 2)); break;
- }
-
- switch (bpc)
- {
- case 1: line[x >> 3] |= value << (7 - (x & 7)); break;
- case 2: line[x >> 2] |= value << ((3 - (x & 3)) << 1); break;
- case 4: line[x >> 1] |= value << ((1 - (x & 1)) << 2); break;
- case 8: line[x] = value; break;
- case 16: line[x << 1] = value >> 8; line[(x << 1) + 1] = value & 0xFF; break;
- }
-}
-
-static const unsigned char png_signature[8] =
-{
- 137, 80, 78, 71, 13, 10, 26, 10
-};
-
-static void *zalloc(void *opaque, unsigned int items, unsigned int size)
-{
- return fz_malloc_array(opaque, items, size);
-}
-
-static void zfree(void *opaque, void *address)
-{
- fz_free(opaque, address);
-}
-
-static inline int paeth(int a, int b, int c)
-{
- /* The definitions of ac and bc are correct, not a typo. */
- int ac = b - c, bc = a - c, abcc = ac + bc;
- int pa = (ac < 0 ? -ac : ac);
- int pb = (bc < 0 ? -bc : bc);
- int pc = (abcc < 0 ? -abcc : abcc);
- return pa <= pb && pa <= pc ? a : pb <= pc ? b : c;
-}
-
-static void
-png_predict(unsigned char *samples, unsigned int width, unsigned int height, unsigned int n, unsigned int depth)
-{
- unsigned int stride = (width * n * depth + 7) / 8;
- unsigned int bpp = (n * depth + 7) / 8;
- unsigned int i, row;
-
- for (row = 0; row < height; row ++)
- {
- unsigned char *src = samples + (unsigned int)((stride + 1) * row);
- unsigned char *dst = samples + (unsigned int)(stride * row);
-
- unsigned char *a = dst;
- unsigned char *b = dst - stride;
- unsigned char *c = dst - stride;
-
- switch (*src++)
- {
- default:
- case 0: /* None */
- for (i = 0; i < stride; i++)
- *dst++ = *src++;
- break;
-
- case 1: /* Sub */
- for (i = 0; i < bpp; i++)
- *dst++ = *src++;
- for (i = bpp; i < stride; i++)
- *dst++ = *src++ + *a++;
- break;
-
- case 2: /* Up */
- if (row == 0)
- for (i = 0; i < stride; i++)
- *dst++ = *src++;
- else
- for (i = 0; i < stride; i++)
- *dst++ = *src++ + *b++;
- break;
-
- case 3: /* Average */
- if (row == 0)
- {
- for (i = 0; i < bpp; i++)
- *dst++ = *src++;
- for (i = bpp; i < stride; i++)
- *dst++ = *src++ + (*a++ >> 1);
- }
- else
- {
- for (i = 0; i < bpp; i++)
- *dst++ = *src++ + (*b++ >> 1);
- for (i = bpp; i < stride; i++)
- *dst++ = *src++ + ((*b++ + *a++) >> 1);
- }
- break;
-
- case 4: /* Paeth */
- if (row == 0)
- {
- for (i = 0; i < bpp; i++)
- *dst++ = *src++ + paeth(0, 0, 0);
- for (i = bpp; i < stride; i++)
- *dst++ = *src++ + paeth(*a++, 0, 0);
- }
- else
- {
- for (i = 0; i < bpp; i++)
- *dst++ = *src++ + paeth(0, *b++, 0);
- for (i = bpp; i < stride; i++)
- *dst++ = *src++ + paeth(*a++, *b++, *c++);
- }
- break;
- }
- }
-}
-
-static const unsigned int adam7_ix[7] = { 0, 4, 0, 2, 0, 1, 0 };
-static const unsigned int adam7_dx[7] = { 8, 8, 4, 4, 2, 2, 1 };
-static const unsigned int adam7_iy[7] = { 0, 0, 4, 0, 2, 0, 1 };
-static const unsigned int adam7_dy[7] = { 8, 8, 8, 4, 4, 2, 2 };
-
-static void
-png_deinterlace_passes(struct info *info, unsigned int *w, unsigned int *h, unsigned int *ofs)
-{
- int p, bpp = info->depth * info->n;
- ofs[0] = 0;
- for (p = 0; p < 7; p++)
- {
- w[p] = (info->width + adam7_dx[p] - adam7_ix[p] - 1) / adam7_dx[p];
- h[p] = (info->height + adam7_dy[p] - adam7_iy[p] - 1) / adam7_dy[p];
- if (w[p] == 0) h[p] = 0;
- if (h[p] == 0) w[p] = 0;
- if (w[p] && h[p])
- ofs[p + 1] = ofs[p] + h[p] * (1 + (w[p] * bpp + 7) / 8);
- else
- ofs[p + 1] = ofs[p];
- }
-}
-
-static void
-png_deinterlace(struct info *info, unsigned int *passw, unsigned int *passh, unsigned int *passofs)
-{
- unsigned int n = info->n;
- unsigned int depth = info->depth;
- unsigned int stride = (info->width * n * depth + 7) / 8;
- unsigned char *output;
- unsigned int p, x, y, k;
-
- output = fz_malloc_array(info->ctx, info->height, stride);
-
- for (p = 0; p < 7; p++)
- {
- unsigned char *sp = info->samples + (passofs[p]);
- unsigned int w = passw[p];
- unsigned int h = passh[p];
-
- png_predict(sp, w, h, n, depth);
- for (y = 0; y < h; y++)
- {
- for (x = 0; x < w; x++)
- {
- int outx = x * adam7_dx[p] + adam7_ix[p];
- int outy = y * adam7_dy[p] + adam7_iy[p];
- unsigned char *dp = output + outy * stride;
- for (k = 0; k < n; k++)
- {
- int v = getcomp(sp, x * n + k, depth);
- putcomp(dp, outx * n + k, depth, v);
- }
- }
- sp += (w * depth * n + 7) / 8;
- }
- }
-
- fz_free(info->ctx, info->samples);
- info->samples = output;
-}
-
-static void
-png_read_ihdr(struct info *info, unsigned char *p, unsigned int size)
-{
- int color, compression, filter;
-
- if (size != 13)
- fz_throw(info->ctx, FZ_ERROR_GENERIC, "IHDR chunk is the wrong size");
-
- info->width = getuint(p + 0);
- info->height = getuint(p + 4);
- info->depth = p[8];
-
- color = p[9];
- compression = p[10];
- filter = p[11];
- info->interlace = p[12];
-
- if (info->width <= 0)
- fz_throw(info->ctx, FZ_ERROR_GENERIC, "image width must be > 0");
- if (info->height <= 0)
- fz_throw(info->ctx, FZ_ERROR_GENERIC, "image height must be > 0");
-
- if (info->depth != 1 && info->depth != 2 && info->depth != 4 &&
- info->depth != 8 && info->depth != 16)
- fz_throw(info->ctx, FZ_ERROR_GENERIC, "image bit depth must be one of 1, 2, 4, 8, 16");
- if (color == 2 && info->depth < 8)
- fz_throw(info->ctx, FZ_ERROR_GENERIC, "illegal bit depth for truecolor");
- if (color == 3 && info->depth > 8)
- fz_throw(info->ctx, FZ_ERROR_GENERIC, "illegal bit depth for indexed");
- if (color == 4 && info->depth < 8)
- fz_throw(info->ctx, FZ_ERROR_GENERIC, "illegal bit depth for grayscale with alpha");
- if (color == 6 && info->depth < 8)
- fz_throw(info->ctx, FZ_ERROR_GENERIC, "illegal bit depth for truecolor with alpha");
-
- info->indexed = 0;
- if (color == 0) /* gray */
- info->n = 1;
- else if (color == 2) /* rgb */
- info->n = 3;
- else if (color == 4) /* gray alpha */
- info->n = 2;
- else if (color == 6) /* rgb alpha */
- info->n = 4;
- else if (color == 3) /* indexed */
- {
- info->indexed = 1;
- info->n = 1;
- }
- else
- fz_throw(info->ctx, FZ_ERROR_GENERIC, "unknown color type");
-
- if (compression != 0)
- fz_throw(info->ctx, FZ_ERROR_GENERIC, "unknown compression method");
- if (filter != 0)
- fz_throw(info->ctx, FZ_ERROR_GENERIC, "unknown filter method");
- if (info->interlace != 0 && info->interlace != 1)
- fz_throw(info->ctx, FZ_ERROR_GENERIC, "interlace method not supported");
-}
-
-static void
-png_read_plte(struct info *info, unsigned char *p, unsigned int size)
-{
- int n = size / 3;
- int i;
-
- if (n > 256)
- {
- fz_warn(info->ctx, "too many samples in palette");
- n = 256;
- }
-
- for (i = 0; i < n; i++)
- {
- info->palette[i * 4] = p[i * 3];
- info->palette[i * 4 + 1] = p[i * 3 + 1];
- info->palette[i * 4 + 2] = p[i * 3 + 2];
- }
-
- /* Fill in any missing palette entries */
- for (; i < 256; i++)
- {
- info->palette[i * 4] = 0;
- info->palette[i * 4 + 1] = 0;
- info->palette[i * 4 + 2] = 0;
- }
-}
-
-static void
-png_read_trns(struct info *info, unsigned char *p, unsigned int size)
-{
- unsigned int i;
-
- info->transparency = 1;
-
- if (info->indexed)
- {
- if (size > 256)
- {
- fz_warn(info->ctx, "too many samples in transparency table");
- size = 256;
- }
- for (i = 0; i < size; i++)
- info->palette[i * 4 + 3] = p[i];
- /* Fill in any missing entries */
- for (; i < 256; i++)
- info->palette[i * 4 + 3] = 255;
- }
- else
- {
- if (size != info->n * 2)
- fz_throw(info->ctx, FZ_ERROR_GENERIC, "tRNS chunk is the wrong size");
- for (i = 0; i < info->n; i++)
- info->trns[i] = (p[i * 2] << 8 | p[i * 2 + 1]) & ((1 << info->depth) - 1);
- }
-}
-
-static void
-png_read_idat(struct info *info, unsigned char *p, unsigned int size, z_stream *stm)
-{
- int code;
-
- stm->next_in = p;
- stm->avail_in = size;
-
- code = inflate(stm, Z_SYNC_FLUSH);
- if (code != Z_OK && code != Z_STREAM_END)
- fz_throw(info->ctx, FZ_ERROR_GENERIC, "zlib error: %s", stm->msg);
- if (stm->avail_in != 0)
- {
- if (stm->avail_out == 0)
- fz_throw(info->ctx, FZ_ERROR_GENERIC, "ran out of output before input");
- fz_throw(info->ctx, FZ_ERROR_GENERIC, "inflate did not consume buffer (%d remaining)", stm->avail_in);
- }
-}
-
-static void
-png_read_phys(struct info *info, unsigned char *p, unsigned int size)
-{
- if (size != 9)
- fz_throw(info->ctx, FZ_ERROR_GENERIC, "pHYs chunk is the wrong size");
- if (p[8] == 1)
- {
- info->xres = getuint(p) * 254 / 10000;
- info->yres = getuint(p + 4) * 254 / 10000;
- }
-}
-
-static void
-png_read_image(fz_context *ctx, struct info *info, unsigned char *p, unsigned int total)
-{
- unsigned int passw[7], passh[7], passofs[8];
- unsigned int code, size;
- z_stream stm;
-
- memset(info, 0, sizeof (struct info));
- info->ctx = ctx;
- memset(info->palette, 255, sizeof(info->palette));
- info->xres = 96;
- info->yres = 96;
-
- /* Read signature */
-
- if (total < 8 + 12 || memcmp(p, png_signature, 8))
- fz_throw(ctx, FZ_ERROR_GENERIC, "not a png image (wrong signature)");
-
- p += 8;
- total -= 8;
-
- /* Read IHDR chunk (must come first) */
-
- size = getuint(p);
- if (total < 12 || size > total - 12)
- fz_throw(ctx, FZ_ERROR_GENERIC, "premature end of data in png image");
-
- if (!memcmp(p + 4, "IHDR", 4))
- png_read_ihdr(info, p + 8, size);
- else
- fz_throw(ctx, FZ_ERROR_GENERIC, "png file must start with IHDR chunk");
-
- p += size + 12;
- total -= size + 12;
-
- /* Prepare output buffer */
-
- if (!info->interlace)
- {
- info->size = info->height * (1 + (info->width * info->n * info->depth + 7) / 8);
- }
- else
- {
- png_deinterlace_passes(info, passw, passh, passofs);
- info->size = passofs[7];
- }
-
- info->samples = fz_malloc(ctx, info->size);
-
- stm.zalloc = zalloc;
- stm.zfree = zfree;
- stm.opaque = ctx;
-
- stm.next_out = info->samples;
- stm.avail_out = info->size;
-
- code = inflateInit(&stm);
- if (code != Z_OK)
- {
- fz_free(ctx, info->samples);
- fz_throw(ctx, FZ_ERROR_GENERIC, "zlib error: %s", stm.msg);
- }
-
- fz_try(ctx)
- {
- /* Read remaining chunks until IEND */
- while (total > 8)
- {
- size = getuint(p);
-
- if (total < 12 || size > total - 12)
- fz_throw(ctx, FZ_ERROR_GENERIC, "premature end of data in png image");
-
- if (!memcmp(p + 4, "PLTE", 4))
- png_read_plte(info, p + 8, size);
- if (!memcmp(p + 4, "tRNS", 4))
- png_read_trns(info, p + 8, size);
- if (!memcmp(p + 4, "pHYs", 4))
- png_read_phys(info, p + 8, size);
- if (!memcmp(p + 4, "IDAT", 4))
- png_read_idat(info, p + 8, size, &stm);
- if (!memcmp(p + 4, "IEND", 4))
- break;
-
- p += size + 12;
- total -= size + 12;
- }
- }
- fz_catch(ctx)
- {
- inflateEnd(&stm);
- fz_free(ctx, info->samples);
- fz_rethrow(ctx);
- }
-
- code = inflateEnd(&stm);
- if (code != Z_OK)
- {
- fz_free(ctx, info->samples);
- fz_throw(ctx, FZ_ERROR_GENERIC, "zlib error: %s", stm.msg);
- }
-
- /* Apply prediction filter and deinterlacing */
- fz_try(ctx)
- {
- if (!info->interlace)
- png_predict(info->samples, info->width, info->height, info->n, info->depth);
- else
- png_deinterlace(info, passw, passh, passofs);
- }
- fz_catch(ctx)
- {
- fz_free(ctx, info->samples);
- fz_rethrow(ctx);
- }
-}
-
-static fz_pixmap *
-png_expand_palette(fz_context *ctx, struct info *info, fz_pixmap *src)
-{
- fz_pixmap *dst = fz_new_pixmap(ctx, fz_device_rgb(ctx), src->w, src->h);
- unsigned char *sp = src->samples;
- unsigned char *dp = dst->samples;
- unsigned int x, y;
-
- dst->xres = src->xres;
- dst->yres = src->yres;
-
- for (y = info->height; y > 0; y--)
- {
- for (x = info->width; x > 0; x--)
- {
- int v = *sp << 2;
- *dp++ = info->palette[v];
- *dp++ = info->palette[v + 1];
- *dp++ = info->palette[v + 2];
- *dp++ = info->palette[v + 3];
- sp += 2;
- }
- }
-
- fz_drop_pixmap(info->ctx, src);
- return dst;
-}
-
-static void
-png_mask_transparency(struct info *info, fz_pixmap *dst)
-{
- unsigned int stride = (info->width * info->n * info->depth + 7) / 8;
- unsigned int depth = info->depth;
- unsigned int n = info->n;
- unsigned int x, y, k, t;
-
- for (y = 0; y < info->height; y++)
- {
- unsigned char *sp = info->samples + (unsigned int)(y * stride);
- unsigned char *dp = dst->samples + (unsigned int)(y * dst->w * dst->n);
- for (x = 0; x < info->width; x++)
- {
- t = 1;
- for (k = 0; k < n; k++)
- if (getcomp(sp, x * n + k, depth) != info->trns[k])
- t = 0;
- if (t)
- dp[x * dst->n + dst->n - 1] = 0;
- }
- }
-}
-
-fz_pixmap *
-fz_load_png(fz_context *ctx, unsigned char *p, int total)
-{
- fz_pixmap *image;
- fz_colorspace *colorspace;
- struct info png;
- int stride;
-
- png_read_image(ctx, &png, p, total);
-
- if (png.n == 3 || png.n == 4)
- colorspace = fz_device_rgb(ctx);
- else
- colorspace = fz_device_gray(ctx);
-
- stride = (png.width * png.n * png.depth + 7) / 8;
-
- fz_try(ctx)
- {
- image = fz_new_pixmap(ctx, colorspace, png.width, png.height);
- }
- fz_catch(ctx)
- {
- fz_free(png.ctx, png.samples);
- fz_rethrow_message(ctx, "out of memory loading png");
- }
-
- image->xres = png.xres;
- image->yres = png.yres;
-
- fz_unpack_tile(image, png.samples, png.n, png.depth, stride, png.indexed);
-
- if (png.indexed)
- image = png_expand_palette(ctx, &png, image);
- else if (png.transparency)
- png_mask_transparency(&png, image);
-
- if (png.transparency || png.n == 2 || png.n == 4)
- fz_premultiply_pixmap(png.ctx, image);
-
- fz_free(png.ctx, png.samples);
-
- return image;
-}
-
-void
-fz_load_png_info(fz_context *ctx, unsigned char *p, int total, int *wp, int *hp, int *xresp, int *yresp, fz_colorspace **cspacep)
-{
- struct info png;
-
- png_read_image(ctx, &png, p, total);
-
- if (png.n == 3 || png.n == 4)
- *cspacep = fz_device_rgb(ctx);
- else
- *cspacep = fz_device_gray(ctx);
-
- *wp = png.width;
- *hp = png.height;
- *xresp = png.xres;
- *yresp = png.xres;
- fz_free(png.ctx, png.samples);
-}
diff --git a/fitz/image_tiff.c b/fitz/image_tiff.c
deleted file mode 100644
index 5806bc00..00000000
--- a/fitz/image_tiff.c
+++ /dev/null
@@ -1,867 +0,0 @@
-#include "mupdf/fitz.h"
-
-/*
- * TIFF image loader. Should be enough to support TIFF files in XPS.
- * Baseline TIFF 6.0 plus CMYK, LZW, Flate and JPEG support.
- * Limited bit depths (1,2,4,8).
- * Limited planar configurations (1=chunky).
- * No tiles (easy fix if necessary).
- * TODO: RGBPal images
- */
-
-struct tiff
-{
- fz_context *ctx;
-
- /* "file" */
- unsigned char *bp, *rp, *ep;
-
- /* byte order */
- unsigned order;
-
- /* where we can find the strips of image data */
- unsigned rowsperstrip;
- unsigned *stripoffsets;
- unsigned *stripbytecounts;
-
- /* colormap */
- unsigned *colormap;
-
- unsigned stripoffsetslen;
- unsigned stripbytecountslen;
- unsigned colormaplen;
-
- /* assorted tags */
- unsigned subfiletype;
- unsigned photometric;
- unsigned compression;
- unsigned imagewidth;
- unsigned imagelength;
- unsigned samplesperpixel;
- unsigned bitspersample;
- unsigned planar;
- unsigned extrasamples;
- unsigned xresolution;
- unsigned yresolution;
- unsigned resolutionunit;
- unsigned fillorder;
- unsigned g3opts;
- unsigned g4opts;
- unsigned predictor;
-
- unsigned ycbcrsubsamp[2];
-
- unsigned char *jpegtables; /* point into "file" buffer */
- unsigned jpegtableslen;
-
- unsigned char *profile;
- int profilesize;
-
- /* decoded data */
- fz_colorspace *colorspace;
- unsigned char *samples;
- int stride;
-};
-
-enum
-{
- TII = 0x4949, /* 'II' */
- TMM = 0x4d4d, /* 'MM' */
- TBYTE = 1,
- TASCII = 2,
- TSHORT = 3,
- TLONG = 4,
- TRATIONAL = 5
-};
-
-#define NewSubfileType 254
-#define ImageWidth 256
-#define ImageLength 257
-#define BitsPerSample 258
-#define Compression 259
-#define PhotometricInterpretation 262
-#define FillOrder 266
-#define StripOffsets 273
-#define SamplesPerPixel 277
-#define RowsPerStrip 278
-#define StripByteCounts 279
-#define XResolution 282
-#define YResolution 283
-#define PlanarConfiguration 284
-#define T4Options 292
-#define T6Options 293
-#define ResolutionUnit 296
-#define Predictor 317
-#define ColorMap 320
-#define TileWidth 322
-#define TileLength 323
-#define TileOffsets 324
-#define TileByteCounts 325
-#define ExtraSamples 338
-#define JPEGTables 347
-#define YCbCrSubSampling 520
-#define ICCProfile 34675
-
-static const unsigned char bitrev[256] =
-{
- 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
- 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
- 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
- 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
- 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
- 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
- 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
- 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
- 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
- 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
- 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
- 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
- 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
- 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
- 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
- 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
- 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
- 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
- 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
- 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
- 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
- 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
- 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
- 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
- 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
- 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
- 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
- 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
- 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
- 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
- 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
- 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
-};
-
-static void
-fz_decode_tiff_uncompressed(struct tiff *tiff, fz_stream *stm, unsigned char *wp, int wlen)
-{
- fz_read(stm, wp, wlen);
- fz_close(stm);
-}
-
-static void
-fz_decode_tiff_packbits(struct tiff *tiff, fz_stream *chain, unsigned char *wp, int wlen)
-{
- fz_stream *stm = fz_open_rld(chain);
- fz_read(stm, wp, wlen);
- fz_close(stm);
-}
-
-static void
-fz_decode_tiff_lzw(struct tiff *tiff, fz_stream *chain, unsigned char *wp, int wlen)
-{
- fz_stream *stm = fz_open_lzwd(chain, 1);
- fz_read(stm, wp, wlen);
- fz_close(stm);
-}
-
-static void
-fz_decode_tiff_flate(struct tiff *tiff, fz_stream *chain, unsigned char *wp, int wlen)
-{
- fz_stream *stm = fz_open_flated(chain);
- fz_read(stm, wp, wlen);
- fz_close(stm);
-}
-
-static void
-fz_decode_tiff_fax(struct tiff *tiff, int comp, fz_stream *chain, unsigned char *wp, int wlen)
-{
- fz_stream *stm;
- int black_is_1 = tiff->photometric == 0;
- int k = comp == 4 ? -1 : 0;
- int encoded_byte_align = comp == 2;
- stm = fz_open_faxd(chain,
- k, 0, encoded_byte_align,
- tiff->imagewidth, tiff->imagelength, 0, black_is_1);
- fz_read(stm, wp, wlen);
- fz_close(stm);
-}
-
-static void
-fz_decode_tiff_jpeg(struct tiff *tiff, fz_stream *chain, unsigned char *wp, int wlen)
-{
- fz_stream *stm = fz_open_dctd(chain, -1);
- fz_read(stm, wp, wlen);
- fz_close(stm);
-}
-
-static inline int getcomp(unsigned char *line, int x, int bpc)
-{
- switch (bpc)
- {
- case 1: return (line[x >> 3] >> ( 7 - (x & 7) ) ) & 1;
- case 2: return (line[x >> 2] >> ( ( 3 - (x & 3) ) << 1 ) ) & 3;
- case 4: return (line[x >> 1] >> ( ( 1 - (x & 1) ) << 2 ) ) & 15;
- case 8: return line[x];
- case 16: return line[x << 1] << 8 | line[(x << 1) + 1];
- }
- return 0;
-}
-
-static inline void putcomp(unsigned char *line, int x, int bpc, int value)
-{
- int maxval = (1 << bpc) - 1;
-
- switch (bpc)
- {
- case 1: line[x >> 3] &= ~(maxval << (7 - (x & 7))); break;
- case 2: line[x >> 2] &= ~(maxval << ((3 - (x & 3)) << 1)); break;
- case 4: line[x >> 1] &= ~(maxval << ((1 - (x & 1)) << 2)); break;
- }
-
- switch (bpc)
- {
- case 1: line[x >> 3] |= value << (7 - (x & 7)); break;
- case 2: line[x >> 2] |= value << ((3 - (x & 3)) << 1); break;
- case 4: line[x >> 1] |= value << ((1 - (x & 1)) << 2); break;
- case 8: line[x] = value; break;
- case 16: line[x << 1] = value >> 8; line[(x << 1) + 1] = value & 0xFF; break;
- }
-}
-
-static void
-fz_unpredict_tiff(unsigned char *line, int width, int comps, int bits)
-{
- unsigned char left[32];
- int i, k, v;
-
- for (k = 0; k < comps; k++)
- left[k] = 0;
-
- for (i = 0; i < width; i++)
- {
- for (k = 0; k < comps; k++)
- {
- v = getcomp(line, i * comps + k, bits);
- v = v + left[k];
- v = v % (1 << bits);
- putcomp(line, i * comps + k, bits, v);
- left[k] = v;
- }
- }
-}
-
-static void
-fz_invert_tiff(unsigned char *line, int width, int comps, int bits, int alpha)
-{
- int i, k, v;
- int m = (1 << bits) - 1;
-
- for (i = 0; i < width; i++)
- {
- for (k = 0; k < comps; k++)
- {
- v = getcomp(line, i * comps + k, bits);
- if (!alpha || k < comps - 1)
- v = m - v;
- putcomp(line, i * comps + k, bits, v);
- }
- }
-}
-
-static void
-fz_expand_tiff_colormap(struct tiff *tiff)
-{
- int maxval = 1 << tiff->bitspersample;
- unsigned char *samples;
- unsigned char *src, *dst;
- unsigned int x, y;
- unsigned int stride;
-
- /* colormap has first all red, then all green, then all blue values */
- /* colormap values are 0..65535, bits is 4 or 8 */
- /* image can be with or without extrasamples: comps is 1 or 2 */
-
- if (tiff->samplesperpixel != 1 && tiff->samplesperpixel != 2)
- fz_throw(tiff->ctx, FZ_ERROR_GENERIC, "invalid number of samples for RGBPal");
-
- if (tiff->bitspersample != 4 && tiff->bitspersample != 8)
- fz_throw(tiff->ctx, FZ_ERROR_GENERIC, "invalid number of bits for RGBPal");
-
- if (tiff->colormaplen < (unsigned)maxval * 3)
- fz_throw(tiff->ctx, FZ_ERROR_GENERIC, "insufficient colormap data");
-
- stride = tiff->imagewidth * (tiff->samplesperpixel + 2);
-
- samples = fz_malloc(tiff->ctx, stride * tiff->imagelength);
-
- for (y = 0; y < tiff->imagelength; y++)
- {
- src = tiff->samples + (unsigned int)(tiff->stride * y);
- dst = samples + (unsigned int)(stride * y);
-
- for (x = 0; x < tiff->imagewidth; x++)
- {
- if (tiff->extrasamples)
- {
- int c = getcomp(src, x * 2, tiff->bitspersample);
- int a = getcomp(src, x * 2 + 1, tiff->bitspersample);
- *dst++ = tiff->colormap[c + 0] >> 8;
- *dst++ = tiff->colormap[c + maxval] >> 8;
- *dst++ = tiff->colormap[c + maxval * 2] >> 8;
- *dst++ = a << (8 - tiff->bitspersample);
- }
- else
- {
- int c = getcomp(src, x, tiff->bitspersample);
- *dst++ = tiff->colormap[c + 0] >> 8;
- *dst++ = tiff->colormap[c + maxval] >> 8;
- *dst++ = tiff->colormap[c + maxval * 2] >> 8;
- }
- }
- }
-
- tiff->samplesperpixel += 2;
- tiff->bitspersample = 8;
- tiff->stride = stride;
- fz_free(tiff->ctx, tiff->samples);
- tiff->samples = samples;
-}
-
-static void
-fz_decode_tiff_strips(struct tiff *tiff)
-{
- fz_stream *stm;
-
- /* switch on compression to create a filter */
- /* feed each strip to the filter */
- /* read out the data and pack the samples into a pixmap */
-
- /* type 32773 / packbits -- nothing special (same row-padding as PDF) */
- /* type 2 / ccitt rle -- no EOL, no RTC, rows are byte-aligned */
- /* type 3 and 4 / g3 and g4 -- each strip starts new section */
- /* type 5 / lzw -- each strip is handled separately */
-
- unsigned char *wp;
- unsigned row;
- unsigned strip;
- unsigned i;
-
- if (!tiff->rowsperstrip || !tiff->stripoffsets || !tiff->stripbytecounts)
- fz_throw(tiff->ctx, FZ_ERROR_GENERIC, "no image data in tiff; maybe it is tiled");
-
- if (tiff->stripoffsetslen < (tiff->imagelength - 1) / tiff->rowsperstrip + 1 ||
- tiff->stripbytecountslen < (tiff->imagelength - 1) / tiff->rowsperstrip + 1)
- fz_throw(tiff->ctx, FZ_ERROR_GENERIC, "insufficient strip offset data");
-
- if (tiff->planar != 1)
- fz_throw(tiff->ctx, FZ_ERROR_GENERIC, "image data is not in chunky format");
-
- tiff->stride = (tiff->imagewidth * tiff->samplesperpixel * tiff->bitspersample + 7) / 8;
-
- switch (tiff->photometric)
- {
- case 0: /* WhiteIsZero -- inverted */
- tiff->colorspace = fz_device_gray(tiff->ctx);
- break;
- case 1: /* BlackIsZero */
- tiff->colorspace = fz_device_gray(tiff->ctx);
- break;
- case 2: /* RGB */
- tiff->colorspace = fz_device_rgb(tiff->ctx);
- break;
- case 3: /* RGBPal */
- tiff->colorspace = fz_device_rgb(tiff->ctx);
- break;
- case 5: /* CMYK */
- tiff->colorspace = fz_device_cmyk(tiff->ctx);
- break;
- case 6: /* YCbCr */
- /* it's probably a jpeg ... we let jpeg convert to rgb */
- tiff->colorspace = fz_device_rgb(tiff->ctx);
- break;
- default:
- fz_throw(tiff->ctx, FZ_ERROR_GENERIC, "unknown photometric: %d", tiff->photometric);
- }
-
- switch (tiff->resolutionunit)
- {
- case 2:
- /* no unit conversion needed */
- break;
- case 3:
- tiff->xresolution = tiff->xresolution * 254 / 100;
- tiff->yresolution = tiff->yresolution * 254 / 100;
- break;
- default:
- tiff->xresolution = 96;
- tiff->yresolution = 96;
- break;
- }
-
- /* Note xres and yres could be 0 even if unit was set. If so default to 96dpi. */
- if (tiff->xresolution == 0 || tiff->yresolution == 0)
- {
- tiff->xresolution = 96;
- tiff->yresolution = 96;
- }
-
- tiff->samples = fz_malloc_array(tiff->ctx, tiff->imagelength, tiff->stride);
- memset(tiff->samples, 0x55, tiff->imagelength * tiff->stride);
- wp = tiff->samples;
-
- strip = 0;
- for (row = 0; row < tiff->imagelength; row += tiff->rowsperstrip)
- {
- unsigned offset = tiff->stripoffsets[strip];
- unsigned rlen = tiff->stripbytecounts[strip];
- unsigned wlen = tiff->stride * tiff->rowsperstrip;
- unsigned char *rp = tiff->bp + offset;
-
- if (wp + wlen > tiff->samples + (unsigned int)(tiff->stride * tiff->imagelength))
- wlen = tiff->samples + (unsigned int)(tiff->stride * tiff->imagelength) - wp;
-
- if (rp + rlen > tiff->ep)
- fz_throw(tiff->ctx, FZ_ERROR_GENERIC, "strip extends beyond the end of the file");
-
- /* the bits are in un-natural order */
- if (tiff->fillorder == 2)
- for (i = 0; i < rlen; i++)
- rp[i] = bitrev[rp[i]];
-
- /* the strip decoders will close this */
- stm = fz_open_memory(tiff->ctx, rp, rlen);
-
- switch (tiff->compression)
- {
- case 1:
- fz_decode_tiff_uncompressed(tiff, stm, wp, wlen);
- break;
- case 2:
- fz_decode_tiff_fax(tiff, 2, stm, wp, wlen);
- break;
- case 3:
- fz_decode_tiff_fax(tiff, 3, stm, wp, wlen);
- break;
- case 4:
- fz_decode_tiff_fax(tiff, 4, stm, wp, wlen);
- break;
- case 5:
- fz_decode_tiff_lzw(tiff, stm, wp, wlen);
- break;
- case 6:
- fz_throw(tiff->ctx, FZ_ERROR_GENERIC, "deprecated JPEG in TIFF compression not supported");
- break;
- case 7:
- fz_decode_tiff_jpeg(tiff, stm, wp, wlen);
- break;
- case 8:
- fz_decode_tiff_flate(tiff, stm, wp, wlen);
- break;
- case 32773:
- fz_decode_tiff_packbits(tiff, stm, wp, wlen);
- break;
- default:
- fz_throw(tiff->ctx, FZ_ERROR_GENERIC, "unknown TIFF compression: %d", tiff->compression);
- }
-
- /* scramble the bits back into original order */
- if (tiff->fillorder == 2)
- for (i = 0; i < rlen; i++)
- rp[i] = bitrev[rp[i]];
-
- wp += tiff->stride * tiff->rowsperstrip;
- strip ++;
- }
-
- /* Predictor (only for LZW and Flate) */
- if ((tiff->compression == 5 || tiff->compression == 8) && tiff->predictor == 2)
- {
- unsigned char *p = tiff->samples;
- for (i = 0; i < tiff->imagelength; i++)
- {
- fz_unpredict_tiff(p, tiff->imagewidth, tiff->samplesperpixel, tiff->bitspersample);
- p += tiff->stride;
- }
- }
-
- /* RGBPal */
- if (tiff->photometric == 3 && tiff->colormap)
- fz_expand_tiff_colormap(tiff);
-
- /* WhiteIsZero .. invert */
- if (tiff->photometric == 0)
- {
- unsigned char *p = tiff->samples;
- for (i = 0; i < tiff->imagelength; i++)
- {
- fz_invert_tiff(p, tiff->imagewidth, tiff->samplesperpixel, tiff->bitspersample, tiff->extrasamples);
- p += tiff->stride;
- }
- }
-
- /* Premultiplied transparency */
- if (tiff->extrasamples == 1)
- {
- /* In GhostXPS we undo the premultiplication here; muxps holds
- * all our images premultiplied by default, so nothing to do.
- */
- }
-
- /* Non-premultiplied transparency */
- if (tiff->extrasamples == 2)
- {
- /* Premultiplied files are corrected for elsewhere */
- }
-}
-
-static inline int readbyte(struct tiff *tiff)
-{
- if (tiff->rp < tiff->ep)
- return *tiff->rp++;
- return EOF;
-}
-
-static inline unsigned readshort(struct tiff *tiff)
-{
- unsigned a = readbyte(tiff);
- unsigned b = readbyte(tiff);
- if (tiff->order == TII)
- return (b << 8) | a;
- return (a << 8) | b;
-}
-
-static inline unsigned readlong(struct tiff *tiff)
-{
- unsigned a = readbyte(tiff);
- unsigned b = readbyte(tiff);
- unsigned c = readbyte(tiff);
- unsigned d = readbyte(tiff);
- if (tiff->order == TII)
- return (d << 24) | (c << 16) | (b << 8) | a;
- return (a << 24) | (b << 16) | (c << 8) | d;
-}
-
-static void
-fz_read_tiff_bytes(unsigned char *p, struct tiff *tiff, unsigned ofs, unsigned n)
-{
- tiff->rp = tiff->bp + ofs;
- if (tiff->rp > tiff->ep)
- tiff->rp = tiff->bp;
-
- while (n--)
- *p++ = readbyte(tiff);
-}
-
-static void
-fz_read_tiff_tag_value(unsigned *p, struct tiff *tiff, unsigned type, unsigned ofs, unsigned n)
-{
- tiff->rp = tiff->bp + ofs;
- if (tiff->rp > tiff->ep)
- tiff->rp = tiff->bp;
-
- while (n--)
- {
- switch (type)
- {
- case TRATIONAL:
- *p = readlong(tiff);
- *p = *p / readlong(tiff);
- p ++;
- break;
- case TBYTE: *p++ = readbyte(tiff); break;
- case TSHORT: *p++ = readshort(tiff); break;
- case TLONG: *p++ = readlong(tiff); break;
- default: *p++ = 0; break;
- }
- }
-}
-
-static void
-fz_read_tiff_tag(struct tiff *tiff, unsigned offset)
-{
- unsigned tag;
- unsigned type;
- unsigned count;
- unsigned value;
-
- tiff->rp = tiff->bp + offset;
-
- tag = readshort(tiff);
- type = readshort(tiff);
- count = readlong(tiff);
-
- if ((type == TBYTE && count <= 4) ||
- (type == TSHORT && count <= 2) ||
- (type == TLONG && count <= 1))
- value = tiff->rp - tiff->bp;
- else
- value = readlong(tiff);
-
- switch (tag)
- {
- case NewSubfileType:
- fz_read_tiff_tag_value(&tiff->subfiletype, tiff, type, value, 1);
- break;
- case ImageWidth:
- fz_read_tiff_tag_value(&tiff->imagewidth, tiff, type, value, 1);
- break;
- case ImageLength:
- fz_read_tiff_tag_value(&tiff->imagelength, tiff, type, value, 1);
- break;
- case BitsPerSample:
- fz_read_tiff_tag_value(&tiff->bitspersample, tiff, type, value, 1);
- break;
- case Compression:
- fz_read_tiff_tag_value(&tiff->compression, tiff, type, value, 1);
- break;
- case PhotometricInterpretation:
- fz_read_tiff_tag_value(&tiff->photometric, tiff, type, value, 1);
- break;
- case FillOrder:
- fz_read_tiff_tag_value(&tiff->fillorder, tiff, type, value, 1);
- break;
- case SamplesPerPixel:
- fz_read_tiff_tag_value(&tiff->samplesperpixel, tiff, type, value, 1);
- break;
- case RowsPerStrip:
- fz_read_tiff_tag_value(&tiff->rowsperstrip, tiff, type, value, 1);
- break;
- case XResolution:
- fz_read_tiff_tag_value(&tiff->xresolution, tiff, type, value, 1);
- break;
- case YResolution:
- fz_read_tiff_tag_value(&tiff->yresolution, tiff, type, value, 1);
- break;
- case PlanarConfiguration:
- fz_read_tiff_tag_value(&tiff->planar, tiff, type, value, 1);
- break;
- case T4Options:
- fz_read_tiff_tag_value(&tiff->g3opts, tiff, type, value, 1);
- break;
- case T6Options:
- fz_read_tiff_tag_value(&tiff->g4opts, tiff, type, value, 1);
- break;
- case Predictor:
- fz_read_tiff_tag_value(&tiff->predictor, tiff, type, value, 1);
- break;
- case ResolutionUnit:
- fz_read_tiff_tag_value(&tiff->resolutionunit, tiff, type, value, 1);
- break;
- case YCbCrSubSampling:
- fz_read_tiff_tag_value(tiff->ycbcrsubsamp, tiff, type, value, 2);
- break;
- case ExtraSamples:
- fz_read_tiff_tag_value(&tiff->extrasamples, tiff, type, value, 1);
- break;
-
- case ICCProfile:
- tiff->profile = fz_malloc(tiff->ctx, count);
- /* ICC profile data type is set to UNDEFINED.
- * TBYTE reading not correct in fz_read_tiff_tag_value */
- fz_read_tiff_bytes(tiff->profile, tiff, value, count);
- tiff->profilesize = count;
- break;
-
- case JPEGTables:
- fz_warn(tiff->ctx, "jpeg tables in tiff not implemented");
- tiff->jpegtables = tiff->bp + value;
- tiff->jpegtableslen = count;
- break;
-
- case StripOffsets:
- tiff->stripoffsets = fz_malloc_array(tiff->ctx, count, sizeof(unsigned));
- fz_read_tiff_tag_value(tiff->stripoffsets, tiff, type, value, count);
- tiff->stripoffsetslen = count;
- break;
-
- case StripByteCounts:
- tiff->stripbytecounts = fz_malloc_array(tiff->ctx, count, sizeof(unsigned));
- fz_read_tiff_tag_value(tiff->stripbytecounts, tiff, type, value, count);
- tiff->stripbytecountslen = count;
- break;
-
- case ColorMap:
- tiff->colormap = fz_malloc_array(tiff->ctx, count, sizeof(unsigned));
- fz_read_tiff_tag_value(tiff->colormap, tiff, type, value, count);
- tiff->colormaplen = count;
- break;
-
- case TileWidth:
- case TileLength:
- case TileOffsets:
- case TileByteCounts:
- fz_throw(tiff->ctx, FZ_ERROR_GENERIC, "tiled tiffs not supported");
-
- default:
- /* printf("unknown tag: %d t=%d n=%d\n", tag, type, count); */
- break;
- }
-}
-
-static void
-fz_swap_tiff_byte_order(unsigned char *buf, int n)
-{
- int i, t;
- for (i = 0; i < n; i++)
- {
- t = buf[i * 2 + 0];
- buf[i * 2 + 0] = buf[i * 2 + 1];
- buf[i * 2 + 1] = t;
- }
-}
-
-static void
-fz_decode_tiff_header(fz_context *ctx, struct tiff *tiff, unsigned char *buf, int len)
-{
- unsigned version;
- unsigned offset;
- unsigned count;
- unsigned i;
-
- memset(tiff, 0, sizeof(struct tiff));
- tiff->ctx = ctx;
- tiff->bp = buf;
- tiff->rp = buf;
- tiff->ep = buf + len;
-
- /* tag defaults, where applicable */
- tiff->bitspersample = 1;
- tiff->compression = 1;
- tiff->samplesperpixel = 1;
- tiff->resolutionunit = 2;
- tiff->rowsperstrip = 0xFFFFFFFF;
- tiff->fillorder = 1;
- tiff->planar = 1;
- tiff->subfiletype = 0;
- tiff->predictor = 1;
- tiff->ycbcrsubsamp[0] = 2;
- tiff->ycbcrsubsamp[1] = 2;
-
- /*
- * Read IFH
- */
-
- /* get byte order marker */
- tiff->order = TII;
- tiff->order = readshort(tiff);
- if (tiff->order != TII && tiff->order != TMM)
- fz_throw(tiff->ctx, FZ_ERROR_GENERIC, "not a TIFF file, wrong magic marker");
-
- /* check version */
- version = readshort(tiff);
- if (version != 42)
- fz_throw(tiff->ctx, FZ_ERROR_GENERIC, "not a TIFF file, wrong version marker");
-
- /* get offset of IFD */
- offset = readlong(tiff);
-
- /*
- * Read IFD
- */
-
- tiff->rp = tiff->bp + offset;
-
- if (tiff->rp < tiff->bp || tiff->rp > tiff->ep)
- fz_throw(tiff->ctx, FZ_ERROR_GENERIC, "invalid IFD offset %u", offset);
-
- count = readshort(tiff);
-
- if (count * 12 > (unsigned)(tiff->ep - tiff->rp))
- fz_throw(tiff->ctx, FZ_ERROR_GENERIC, "overlarge IFD entry count %u", count);
-
- offset += 2;
- for (i = 0; i < count; i++)
- {
- fz_read_tiff_tag(tiff, offset);
- offset += 12;
- }
-}
-
-fz_pixmap *
-fz_load_tiff(fz_context *ctx, unsigned char *buf, int len)
-{
- fz_pixmap *image;
- struct tiff tiff;
-
- fz_try(ctx)
- {
- fz_decode_tiff_header(ctx, &tiff, buf, len);
-
- /* Decode the image strips */
-
- if (tiff.rowsperstrip > tiff.imagelength)
- tiff.rowsperstrip = tiff.imagelength;
-
- fz_decode_tiff_strips(&tiff);
-
- /* Byte swap 16-bit images to big endian if necessary */
- if (tiff.bitspersample == 16)
- if (tiff.order == TII)
- fz_swap_tiff_byte_order(tiff.samples, tiff.imagewidth * tiff.imagelength * tiff.samplesperpixel);
-
- /* Expand into fz_pixmap struct */
- image = fz_new_pixmap(tiff.ctx, tiff.colorspace, tiff.imagewidth, tiff.imagelength);
- image->xres = tiff.xresolution;
- image->yres = tiff.yresolution;
-
- fz_unpack_tile(image, tiff.samples, tiff.samplesperpixel, tiff.bitspersample, tiff.stride, 0);
-
- /* We should only do this on non-pre-multiplied images, but files in the wild are bad */
- if (tiff.extrasamples /* == 2 */)
- {
- /* CMYK is a subtractive colorspace, we want additive for premul alpha */
- if (image->n == 5)
- {
- fz_pixmap *rgb = fz_new_pixmap(tiff.ctx, fz_device_rgb(ctx), image->w, image->h);
- fz_convert_pixmap(tiff.ctx, rgb, image);
- rgb->xres = image->xres;
- rgb->yres = image->yres;
- fz_drop_pixmap(ctx, image);
- image = rgb;
- }
- fz_premultiply_pixmap(ctx, image);
- }
- }
- fz_always(ctx)
- {
- /* Clean up scratch memory */
- if (tiff.colormap) fz_free(ctx, tiff.colormap);
- if (tiff.stripoffsets) fz_free(ctx, tiff.stripoffsets);
- if (tiff.stripbytecounts) fz_free(ctx, tiff.stripbytecounts);
- if (tiff.samples) fz_free(ctx, tiff.samples);
- if (tiff.profile) fz_free(ctx, tiff.profile);
- }
- fz_catch(ctx)
- {
- fz_rethrow_message(ctx, "out of memory loading tiff");
- }
-
- return image;
-}
-
-void
-fz_load_tiff_info(fz_context *ctx, unsigned char *buf, int len, int *wp, int *hp, int *xresp, int *yresp, fz_colorspace **cspacep)
-{
- struct tiff tiff;
-
- fz_try(ctx)
- {
- fz_decode_tiff_header(ctx, &tiff, buf, len);
-
- *wp = tiff.imagewidth;
- *hp = tiff.imagelength;
- *xresp = tiff.xresolution;
- *yresp = tiff.yresolution;
- *cspacep = tiff.colorspace;
- }
- fz_always(ctx)
- {
- /* Clean up scratch memory */
- if (tiff.colormap) fz_free(ctx, tiff.colormap);
- if (tiff.stripoffsets) fz_free(ctx, tiff.stripoffsets);
- if (tiff.stripbytecounts) fz_free(ctx, tiff.stripbytecounts);
- if (tiff.samples) fz_free(ctx, tiff.samples);
- if (tiff.profile) fz_free(ctx, tiff.profile);
- }
- fz_catch(ctx)
- {
- fz_rethrow_message(ctx, "out of memory loading tiff");
- }
-}
diff --git a/fitz/memento.c b/fitz/memento.c
deleted file mode 100644
index 6a159f10..00000000
--- a/fitz/memento.c
+++ /dev/null
@@ -1,1535 +0,0 @@
-/* Copyright (C) 2001-2013 Artifex Software, Inc.
- All Rights Reserved.
-
- This software is provided AS-IS with no warranty, either express or
- implied.
-
- This software is distributed under license and may not be copied, modified
- or distributed except as expressly authorized under the terms of that
- license. Refer to licensing information at http://www.artifex.com
- or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
- San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
-*/
-
-/* Inspired by Fortify by Simon P Bullen. */
-
-/* Set the following if you're only looking for leaks, not memory overwrites
- * to speed the operation */
-/* #define MEMENTO_LEAKONLY */
-
-/* Don't keep blocks around if they'd mean losing more than a quarter of
- * the freelist. */
-#define MEMENTO_FREELIST_MAX_SINGLE_BLOCK (MEMENTO_FREELIST_MAX/4)
-
-#define COMPILING_MEMENTO_C
-
-/* We have some GS specific tweaks; more for the GS build environment than
- * anything else. */
-#undef MEMENTO_GS_HACKS
-
-#ifdef MEMENTO_GS_HACKS
-/* For GS we include malloc_.h. Anyone else would just include memento.h */
-#include "malloc_.h"
-#ifdef __MACH__
-#include <string.h>
-#else
-#ifndef memset
-void *memset(void *,int,size_t);
-#endif
-#endif
-int atexit(void (*)(void));
-#else
-#include "mupdf/memento.h"
-#include <stdio.h>
-#include <stdlib.h>
-#endif
-
-#ifdef MEMENTO_ANDROID
-#include <android/log.h>
-
-static int
-android_fprintf(FILE *file, const char *fmt, ...)
-{
- va_list args;
-
- va_start(args, fmt);
- __android_log_vprint(ANDROID_LOG_ERROR,"memento", fmt, args);
- va_end(args);
-}
-
-#define fprintf android_fprintf
-#define MEMENTO_STACKTRACE_METHOD 0
-#endif
-
-#ifndef MEMENTO_STACKTRACE_METHOD
-#ifdef __GNUC__
-#define MEMENTO_STACKTRACE_METHOD 1
-#endif
-#endif
-
-#if defined(__linux__)
-#define MEMENTO_HAS_FORK
-#elif defined(__APPLE__) && defined(__MACH__)
-#define MEMENTO_HAS_FORK
-#endif
-
-/* Define the underlying allocators, just in case */
-void *MEMENTO_UNDERLYING_MALLOC(size_t);
-void MEMENTO_UNDERLYING_FREE(void *);
-void *MEMENTO_UNDERLYING_REALLOC(void *,size_t);
-void *MEMENTO_UNDERLYING_CALLOC(size_t,size_t);
-
-/* And some other standard functions we use. We don't include the header
- * files, just in case they pull in unexpected others. */
-int atoi(const char *);
-char *getenv(const char *);
-
-/* How far to search for pointers in each block when calculating nestings */
-/* mupdf needs at least 34000ish (sizeof(fz_shade))/ */
-#define MEMENTO_PTRSEARCH 65536
-
-#ifndef MEMENTO_MAXPATTERN
-#define MEMENTO_MAXPATTERN 0
-#endif
-
-#ifdef MEMENTO
-
-#ifdef MEMENTO_GS_HACKS
-#include "valgrind.h"
-#else
-#ifdef HAVE_VALGRIND
-#include "valgrind/memcheck.h"
-#else
-#define VALGRIND_MAKE_MEM_NOACCESS(p,s) do { } while (0==1)
-#define VALGRIND_MAKE_MEM_UNDEFINED(p,s) do { } while (0==1)
-#define VALGRIND_MAKE_MEM_DEFINED(p,s) do { } while (0==1)
-#endif
-#endif
-
-enum {
- Memento_PreSize = 16,
- Memento_PostSize = 16
-};
-
-enum {
- Memento_Flag_OldBlock = 1,
- Memento_Flag_HasParent = 2,
- Memento_Flag_BreakOnFree = 4,
- Memento_Flag_BreakOnRealloc = 8
-};
-
-/* When we list leaked blocks at the end of execution, we search for pointers
- * between blocks in order to be able to give a nice nested view.
- * Unfortunately, if you have are running your own allocator (such as
- * ghostscripts chunk allocator) you can often find that the header of the
- * block always contains pointers to next or previous blocks. This tends to
- * mean the nesting displayed is "uninteresting" at best :)
- *
- * As a hack to get around this, we have a define MEMENTO_SKIP_SEARCH that
- * indicates how many bytes to skip over at the start of the chunk.
- * This may cause us to miss true nestings, but such is life...
- */
-#ifndef MEMENTO_SEARCH_SKIP
-#ifdef MEMENTO_GS_HACKS
-#define MEMENTO_SEARCH_SKIP (2*sizeof(void *))
-#else
-#define MEMENTO_SEARCH_SKIP 0
-#endif
-#endif
-
-typedef struct Memento_BlkHeader Memento_BlkHeader;
-
-struct Memento_BlkHeader
-{
- size_t rawsize;
- int sequence;
- int lastCheckedOK;
- int flags;
- Memento_BlkHeader *next;
- Memento_BlkHeader *parent; /* Only used while printing out nested list */
-
- const char *label;
-
- /* Entries for nesting display calculations */
- Memento_BlkHeader *child;
- Memento_BlkHeader *sibling;
-
- char preblk[Memento_PreSize];
-};
-
-/* In future this could (should) be a smarter data structure, like, say,
- * splay trees. For now, we use a list.
- */
-typedef struct Memento_Blocks
-{
- Memento_BlkHeader *head;
- Memento_BlkHeader **tail;
-} Memento_Blocks;
-
-/* And our global structure */
-static struct {
- int inited;
- Memento_Blocks used;
- Memento_Blocks free;
- size_t freeListSize;
- int sequence;
- int paranoia;
- int paranoidAt;
- int countdown;
- int lastChecked;
- int breakAt;
- int failAt;
- int failing;
- int nextFailAt;
- int squeezeAt;
- int squeezing;
- int segv;
- int pattern;
- int nextPattern;
- int patternBit;
- size_t maxMemory;
- size_t alloc;
- size_t peakAlloc;
- size_t totalAlloc;
- size_t numMallocs;
- size_t numFrees;
- size_t numReallocs;
-} globals;
-
-#define MEMENTO_EXTRASIZE (sizeof(Memento_BlkHeader) + Memento_PostSize)
-
-/* Round up size S to the next multiple of N (where N is a power of 2) */
-#define MEMENTO_ROUNDUP(S,N) ((S + N-1)&~(N-1))
-
-#define MEMBLK_SIZE(s) MEMENTO_ROUNDUP(s + MEMENTO_EXTRASIZE, MEMENTO_MAXALIGN)
-
-#define MEMBLK_FROMBLK(B) (&((Memento_BlkHeader*)(void *)(B))[-1])
-#define MEMBLK_TOBLK(B) ((void*)(&((Memento_BlkHeader*)(void*)(B))[1]))
-#define MEMBLK_POSTPTR(B) \
- (&((char *)(void *)(B))[(B)->rawsize + sizeof(Memento_BlkHeader)])
-
-void Memento_breakpoint(void)
-{
- /* A handy externally visible function for breakpointing */
-#if 0 /* Enable this to force automatic breakpointing */
-#ifdef DEBUG
-#ifdef _MSC_VER
- __asm int 3;
-#endif
-#endif
-#endif
-}
-
-static void Memento_addBlockHead(Memento_Blocks *blks,
- Memento_BlkHeader *b,
- int type)
-{
- if (blks->tail == &blks->head) {
- /* Adding into an empty list, means the tail changes too */
- blks->tail = &b->next;
- }
- b->next = blks->head;
- blks->head = b;
-#ifndef MEMENTO_LEAKONLY
- memset(b->preblk, MEMENTO_PREFILL, Memento_PreSize);
- memset(MEMBLK_POSTPTR(b), MEMENTO_POSTFILL, Memento_PostSize);
-#endif
- VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(b), Memento_PostSize);
- if (type == 0) { /* malloc */
- VALGRIND_MAKE_MEM_UNDEFINED(MEMBLK_TOBLK(b), b->rawsize);
- } else if (type == 1) { /* free */
- VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_TOBLK(b), b->rawsize);
- }
- VALGRIND_MAKE_MEM_NOACCESS(b, sizeof(Memento_BlkHeader));
-}
-
-static void Memento_addBlockTail(Memento_Blocks *blks,
- Memento_BlkHeader *b,
- int type)
-{
- VALGRIND_MAKE_MEM_DEFINED(blks->tail, sizeof(Memento_BlkHeader *));
- *blks->tail = b;
- blks->tail = &b->next;
- b->next = NULL;
- VALGRIND_MAKE_MEM_NOACCESS(blks->tail, sizeof(Memento_BlkHeader *));
-#ifndef MEMENTO_LEAKONLY
- memset(b->preblk, MEMENTO_PREFILL, Memento_PreSize);
- memset(MEMBLK_POSTPTR(b), MEMENTO_POSTFILL, Memento_PostSize);
-#endif
- VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(b), Memento_PostSize);
- if (type == 0) { /* malloc */
- VALGRIND_MAKE_MEM_UNDEFINED(MEMBLK_TOBLK(b), b->rawsize);
- } else if (type == 1) { /* free */
- VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_TOBLK(b), b->rawsize);
- }
- VALGRIND_MAKE_MEM_NOACCESS(b, sizeof(Memento_BlkHeader));
-}
-
-typedef struct BlkCheckData {
- int found;
- int preCorrupt;
- int postCorrupt;
- int freeCorrupt;
- int index;
-} BlkCheckData;
-
-static int Memento_Internal_checkAllocedBlock(Memento_BlkHeader *b, void *arg)
-{
-#ifndef MEMENTO_LEAKONLY
- int i;
- char *p;
- int corrupt = 0;
- BlkCheckData *data = (BlkCheckData *)arg;
-
- p = b->preblk;
- i = Memento_PreSize;
- do {
- corrupt |= (*p++ ^ (char)MEMENTO_PREFILL);
- } while (--i);
- if (corrupt) {
- data->preCorrupt = 1;
- }
- p = MEMBLK_POSTPTR(b);
- i = Memento_PreSize;
- do {
- corrupt |= (*p++ ^ (char)MEMENTO_POSTFILL);
- } while (--i);
- if (corrupt) {
- data->postCorrupt = 1;
- }
- if ((data->freeCorrupt | data->preCorrupt | data->postCorrupt) == 0) {
- b->lastCheckedOK = globals.sequence;
- }
- data->found |= 1;
-#endif
- return 0;
-}
-
-static int Memento_Internal_checkFreedBlock(Memento_BlkHeader *b, void *arg)
-{
-#ifndef MEMENTO_LEAKONLY
- int i;
- char *p;
- BlkCheckData *data = (BlkCheckData *)arg;
-
- p = MEMBLK_TOBLK(b);
- i = b->rawsize;
- /* Attempt to speed this up by checking an (aligned) int at a time */
- do {
- if (((size_t)p) & 1) {
- if (*p++ != (char)MEMENTO_FREEFILL)
- break;
- i--;
- if (i == 0)
- break;
- }
- if ((i >= 2) && (((size_t)p) & 2)) {
- if (*(short *)p != (short)(MEMENTO_FREEFILL | (MEMENTO_FREEFILL<<8)))
- goto mismatch;
- p += 2;
- i -= 2;
- if (i == 0)
- break;
- }
- i -= 4;
- while (i >= 0) {
- if (*(int *)p != (MEMENTO_FREEFILL |
- (MEMENTO_FREEFILL<<8) |
- (MEMENTO_FREEFILL<<16) |
- (MEMENTO_FREEFILL<<24)))
- goto mismatch;
- p += 4;
- i -= 4;
- }
- i += 4;
- if ((i >= 2) && (((size_t)p) & 2)) {
- if (*(short *)p != (short)(MEMENTO_FREEFILL | (MEMENTO_FREEFILL<<8)))
- goto mismatch;
- p += 2;
- i -= 2;
- }
-mismatch:
- while (i) {
- if (*p++ != (char)MEMENTO_FREEFILL)
- break;
- i--;
- }
- } while (0);
- if (i) {
- data->freeCorrupt = 1;
- data->index = b->rawsize-i;
- }
- return Memento_Internal_checkAllocedBlock(b, arg);
-#else
- return 0;
-#endif
-}
-
-static void Memento_removeBlock(Memento_Blocks *blks,
- Memento_BlkHeader *b)
-{
- Memento_BlkHeader *head = blks->head;
- Memento_BlkHeader *prev = NULL;
- while ((head) && (head != b)) {
- VALGRIND_MAKE_MEM_DEFINED(head, sizeof(*head));
- prev = head;
- head = head->next;
- VALGRIND_MAKE_MEM_NOACCESS(prev, sizeof(*prev));
- }
- if (head == NULL) {
- /* FAIL! Will have been reported to user earlier, so just exit. */
- return;
- }
- VALGRIND_MAKE_MEM_DEFINED(blks->tail, sizeof(*blks->tail));
- if (*blks->tail == head) {
- /* Removing the tail of the list */
- if (prev == NULL) {
- /* Which is also the head */
- blks->tail = &blks->head;
- } else {
- /* Which isn't the head */
- blks->tail = &prev->next;
- }
- }
- if (prev == NULL) {
- /* Removing from the head of the list */
- VALGRIND_MAKE_MEM_DEFINED(head, sizeof(*head));
- blks->head = head->next;
- VALGRIND_MAKE_MEM_NOACCESS(head, sizeof(*head));
- } else {
- /* Removing from not-the-head */
- VALGRIND_MAKE_MEM_DEFINED(head, sizeof(*head));
- VALGRIND_MAKE_MEM_DEFINED(prev, sizeof(*prev));
- prev->next = head->next;
- VALGRIND_MAKE_MEM_NOACCESS(head, sizeof(*head));
- VALGRIND_MAKE_MEM_NOACCESS(prev, sizeof(*prev));
- }
-}
-
-static int Memento_Internal_makeSpace(size_t space)
-{
- /* If too big, it can never go on the freelist */
- if (space > MEMENTO_FREELIST_MAX_SINGLE_BLOCK)
- return 0;
- /* Pretend we added it on. */
- globals.freeListSize += space;
- /* Ditch blocks until it fits within our limit */
- while (globals.freeListSize > MEMENTO_FREELIST_MAX) {
- Memento_BlkHeader *head = globals.free.head;
- VALGRIND_MAKE_MEM_DEFINED(head, sizeof(*head));
- globals.free.head = head->next;
- globals.freeListSize -= MEMBLK_SIZE(head->rawsize);
- MEMENTO_UNDERLYING_FREE(head);
- }
- /* Make sure we haven't just completely emptied the free list */
- /* (This should never happen, but belt and braces... */
- if (globals.free.head == NULL)
- globals.free.tail = &globals.free.head;
- return 1;
-}
-
-static int Memento_appBlocks(Memento_Blocks *blks,
- int (*app)(Memento_BlkHeader *,
- void *),
- void *arg)
-{
- Memento_BlkHeader *head = blks->head;
- Memento_BlkHeader *next;
- int result;
- while (head) {
- VALGRIND_MAKE_MEM_DEFINED(head, sizeof(Memento_BlkHeader));
- VALGRIND_MAKE_MEM_DEFINED(MEMBLK_TOBLK(head),
- head->rawsize + Memento_PostSize);
- result = app(head, arg);
- next = head->next;
- VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(head), Memento_PostSize);
- VALGRIND_MAKE_MEM_NOACCESS(head, sizeof(Memento_BlkHeader));
- if (result)
- return result;
- head = next;
- }
- return 0;
-}
-
-static int Memento_appBlock(Memento_Blocks *blks,
- int (*app)(Memento_BlkHeader *,
- void *),
- void *arg,
- Memento_BlkHeader *b)
-{
- Memento_BlkHeader *head = blks->head;
- Memento_BlkHeader *next;
- int result;
- while (head && head != b) {
- VALGRIND_MAKE_MEM_DEFINED(head, sizeof(Memento_BlkHeader));
- next = head->next;
- VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(head), Memento_PostSize);
- head = next;
- }
- if (head == b) {
- VALGRIND_MAKE_MEM_DEFINED(head, sizeof(Memento_BlkHeader));
- VALGRIND_MAKE_MEM_DEFINED(MEMBLK_TOBLK(head),
- head->rawsize + Memento_PostSize);
- result = app(head, arg);
- VALGRIND_MAKE_MEM_NOACCESS(MEMBLK_POSTPTR(head), Memento_PostSize);
- VALGRIND_MAKE_MEM_NOACCESS(head, sizeof(Memento_BlkHeader));
- return result;
- }
- return 0;
-}
-
-static void showBlock(Memento_BlkHeader *b, int space)
-{
- fprintf(stderr, "0x%p:(size=%d,num=%d)",
- MEMBLK_TOBLK(b), (int)b->rawsize, b->sequence);
- if (b->label)
- fprintf(stderr, "%c(%s)", space, b->label);
-}
-
-static void blockDisplay(Memento_BlkHeader *b, int n)
-{
- n++;
- while (n > 40)
- {
- fprintf(stderr, "*");
- n -= 40;
- }
- while(n > 0)
- {
- int i = n;
- if (i > 32)
- i = 32;
- n -= i;
- fprintf(stderr, "%s", &" "[32-i]);
- }
- showBlock(b, '\t');
- fprintf(stderr, "\n");
-}
-
-static int Memento_listBlock(Memento_BlkHeader *b,
- void *arg)
-{
- int *counts = (int *)arg;
- blockDisplay(b, 0);
- counts[0]++;
- counts[1]+= b->rawsize;
- return 0;
-}
-
-static void doNestedDisplay(Memento_BlkHeader *b,
- int depth)
-{
- /* Try and avoid recursion if we can help it */
- do {
- blockDisplay(b, depth);
- if (b->sibling) {
- if (b->child)
- doNestedDisplay(b->child, depth+1);
- b = b->sibling;
- } else {
- b = b->child;
- depth++;
- }
- } while (b);
-}
-
-static int ptrcmp(const void *a_, const void *b_)
-{
- const char **a = (const char **)a_;
- const char **b = (const char **)b_;
- return (int)(*a-*b);
-}
-
-static
-int Memento_listBlocksNested(void)
-{
- int count, size, i;
- Memento_BlkHeader *b;
- void **blocks, *minptr, *maxptr;
- long mask;
-
- /* Count the blocks */
- count = 0;
- size = 0;
- for (b = globals.used.head; b; b = b->next) {
- size += b->rawsize;
- count++;
- }
-
- /* Make our block list */
- blocks = MEMENTO_UNDERLYING_MALLOC(sizeof(void *) * count);
- if (blocks == NULL)
- return 1;
-
- /* Populate our block list */
- b = globals.used.head;
- minptr = maxptr = MEMBLK_TOBLK(b);
- mask = (long)minptr;
- for (i = 0; b; b = b->next, i++) {
- void *p = MEMBLK_TOBLK(b);
- mask &= (long)p;
- if (p < minptr)
- minptr = p;
- if (p > maxptr)
- maxptr = p;
- blocks[i] = p;
- b->flags &= ~Memento_Flag_HasParent;
- b->child = NULL;
- b->sibling = NULL;
- b->parent = NULL;
- }
- qsort(blocks, count, sizeof(void *), ptrcmp);
-
- /* Now, calculate tree */
- for (b = globals.used.head; b; b = b->next) {
- char *p = MEMBLK_TOBLK(b);
- int end = (b->rawsize < MEMENTO_PTRSEARCH ? b->rawsize : MEMENTO_PTRSEARCH);
- for (i = MEMENTO_SEARCH_SKIP; i < end; i += sizeof(void *)) {
- void *q = *(void **)(&p[i]);
- void **r;
-
- /* Do trivial checks on pointer */
- if ((mask & (int)q) != mask || q < minptr || q > maxptr)
- continue;
-
- /* Search for pointer */
- r = bsearch(&q, blocks, count, sizeof(void *), ptrcmp);
- if (r) {
- /* Found child */
- Memento_BlkHeader *child = MEMBLK_FROMBLK(*r);
- Memento_BlkHeader *parent;
-
- /* We're assuming tree structure, not graph - ignore second
- * and subsequent pointers. */
- if (child->parent != NULL)
- continue;
- if (child->flags & Memento_Flag_HasParent)
- continue;
-
- /* We're also assuming acyclicness here. If this is one of
- * our parents, ignore it. */
- parent = b->parent;
- while (parent != NULL && parent != child)
- parent = parent->parent;
- if (parent == child)
- continue;
-
- child->sibling = b->child;
- b->child = child;
- child->parent = b;
- child->flags |= Memento_Flag_HasParent;
- }
- }
- }
-
- /* Now display with nesting */
- for (b = globals.used.head; b; b = b->next) {
- if ((b->flags & Memento_Flag_HasParent) == 0)
- doNestedDisplay(b, 0);
- }
- fprintf(stderr, " Total number of blocks = %d\n", count);
- fprintf(stderr, " Total size of blocks = %d\n", size);
-
- MEMENTO_UNDERLYING_FREE(blocks);
- return 0;
-}
-
-void Memento_listBlocks(void)
-{
- fprintf(stderr, "Allocated blocks:\n");
- if (Memento_listBlocksNested())
- {
- int counts[2];
- counts[0] = 0;
- counts[1] = 0;
- Memento_appBlocks(&globals.used, Memento_listBlock, &counts[0]);
- fprintf(stderr, " Total number of blocks = %d\n", counts[0]);
- fprintf(stderr, " Total size of blocks = %d\n", counts[1]);
- }
-}
-
-static int Memento_listNewBlock(Memento_BlkHeader *b,
- void *arg)
-{
- if (b->flags & Memento_Flag_OldBlock)
- return 0;
- b->flags |= Memento_Flag_OldBlock;
- return Memento_listBlock(b, arg);
-}
-
-void Memento_listNewBlocks(void) {
- int counts[2];
- counts[0] = 0;
- counts[1] = 0;
- fprintf(stderr, "Blocks allocated and still extant since last list:\n");
- Memento_appBlocks(&globals.used, Memento_listNewBlock, &counts[0]);
- fprintf(stderr, " Total number of blocks = %d\n", counts[0]);
- fprintf(stderr, " Total size of blocks = %d\n", counts[1]);
-}
-
-static void Memento_endStats(void)
-{
- fprintf(stderr, "Total memory malloced = %u bytes\n", (unsigned int)globals.totalAlloc);
- fprintf(stderr, "Peak memory malloced = %u bytes\n", (unsigned int)globals.peakAlloc);
- fprintf(stderr, "%u mallocs, %u frees, %u reallocs\n", (unsigned int)globals.numMallocs,
- (unsigned int)globals.numFrees, (unsigned int)globals.numReallocs);
- fprintf(stderr, "Average allocation size %u bytes\n", (unsigned int)
- (globals.numMallocs != 0 ? globals.totalAlloc/globals.numMallocs: 0));
-}
-
-void Memento_stats(void)
-{
- fprintf(stderr, "Current memory malloced = %u bytes\n", (unsigned int)globals.alloc);
- Memento_endStats();
-}
-
-static void Memento_fin(void)
-{
- Memento_checkAllMemory();
- Memento_endStats();
- if (globals.used.head != NULL) {
- Memento_listBlocks();
- Memento_breakpoint();
- }
- if (globals.segv) {
- fprintf(stderr, "Memory dumped on SEGV while squeezing @ %d\n", globals.failAt);
- } else if (globals.squeezing) {
- if (globals.pattern == 0)
- fprintf(stderr, "Memory squeezing @ %d complete\n", globals.squeezeAt);
- else
- fprintf(stderr, "Memory squeezing @ %d (%d) complete\n", globals.squeezeAt, globals.pattern);
- }
- if (globals.failing)
- {
- fprintf(stderr, "MEMENTO_FAILAT=%d\n", globals.failAt);
- fprintf(stderr, "MEMENTO_PATTERN=%d\n", globals.pattern);
- }
- if (globals.nextFailAt != 0)
- {
- fprintf(stderr, "MEMENTO_NEXTFAILAT=%d\n", globals.nextFailAt);
- fprintf(stderr, "MEMENTO_NEXTPATTERN=%d\n", globals.nextPattern);
- }
-}
-
-static void Memento_inited(void)
-{
- /* A good place for a breakpoint */
-}
-
-static void Memento_init(void)
-{
- char *env;
- memset(&globals, 0, sizeof(globals));
- globals.inited = 1;
- globals.used.head = NULL;
- globals.used.tail = &globals.used.head;
- globals.free.head = NULL;
- globals.free.tail = &globals.free.head;
- globals.sequence = 0;
- globals.countdown = 1024;
-
- env = getenv("MEMENTO_FAILAT");
- globals.failAt = (env ? atoi(env) : 0);
-
- env = getenv("MEMENTO_PARANOIA");
- globals.paranoia = (env ? atoi(env) : 0);
- if (globals.paranoia == 0)
- globals.paranoia = 1024;
-
- env = getenv("MEMENTO_PARANOIDAT");
- globals.paranoidAt = (env ? atoi(env) : 0);
-
- env = getenv("MEMENTO_SQUEEZEAT");
- globals.squeezeAt = (env ? atoi(env) : 0);
-
- env = getenv("MEMENTO_PATTERN");
- globals.pattern = (env ? atoi(env) : 0);
-
- env = getenv("MEMENTO_MAXMEMORY");
- globals.maxMemory = (env ? atoi(env) : 0);
-
- atexit(Memento_fin);
-
- Memento_inited();
-}
-
-#ifdef MEMENTO_HAS_FORK
-#include <unistd.h>
-#include <sys/wait.h>
-#ifdef MEMENTO_STACKTRACE_METHOD
-#if MEMENTO_STACKTRACE_METHOD == 1
-#include <signal.h>
-#endif
-#endif
-
-/* FIXME: Find some portable way of getting this */
-/* MacOSX has 10240, Ubuntu seems to have 256 */
-#define OPEN_MAX 10240
-
-/* stashed_map[j] = i means that filedescriptor i-1 was duplicated to j */
-int stashed_map[OPEN_MAX];
-
-#ifdef MEMENTO_STACKTRACE_METHOD
-#if MEMENTO_STACKTRACE_METHOD == 1
-extern size_t backtrace(void **, int);
-extern void backtrace_symbols_fd(void **, size_t, int);
-#endif
-#endif
-
-static void Memento_signal(void)
-{
- fprintf(stderr, "SEGV after Memory squeezing @ %d\n", globals.squeezeAt);
-
-#ifdef MEMENTO_STACKTRACE_METHOD
-#if MEMENTO_STACKTRACE_METHOD == 1
- {
- void *array[100];
- size_t size;
-
- size = backtrace(array, 100);
- fprintf(stderr, "------------------------------------------------------------------------\n");
- fprintf(stderr, "Backtrace:\n");
- backtrace_symbols_fd(array, size, 2);
- fprintf(stderr, "------------------------------------------------------------------------\n");
- }
-#endif
-#endif
-
- exit(1);
-}
-
-static int squeeze(void)
-{
- pid_t pid;
- int i, status;
-
- if (globals.patternBit < 0)
- return 1;
- if (globals.squeezing && globals.patternBit >= MEMENTO_MAXPATTERN)
- return 1;
-
- if (globals.patternBit == 0)
- globals.squeezeAt = globals.sequence;
-
- if (!globals.squeezing) {
- fprintf(stderr, "Memory squeezing @ %d\n", globals.squeezeAt);
- } else
- fprintf(stderr, "Memory squeezing @ %d (%x,%x)\n", globals.squeezeAt, globals.pattern, globals.patternBit);
-
- /* When we fork below, the child is going to snaffle all our file pointers
- * and potentially corrupt them. Let's make copies of all of them before
- * we fork, so we can restore them when we restart. */
- for (i = 0; i < OPEN_MAX; i++) {
- if (stashed_map[i] == 0) {
- int j = dup(i);
- stashed_map[j] = i+1;
- }
- }
-
- pid = fork();
- if (pid == 0) {
- /* Child */
- signal(SIGSEGV, Memento_signal);
- /* In the child, we always fail the next allocation. */
- if (globals.patternBit == 0) {
- globals.patternBit = 1;
- } else
- globals.patternBit <<= 1;
- globals.squeezing = 1;
- return 1;
- }
-
- /* In the parent if we hit another allocation, pass it (and record the
- * fact we passed it in the pattern. */
- globals.pattern |= globals.patternBit;
- globals.patternBit <<= 1;
-
- /* Wait for pid to finish */
- waitpid(pid, &status, 0);
-
- if (status != 0) {
- fprintf(stderr, "Child status=%d\n", status);
- }
-
- /* Put the files back */
- for (i = 0; i < OPEN_MAX; i++) {
- if (stashed_map[i] != 0) {
- dup2(i, stashed_map[i]-1);
- close(i);
- stashed_map[i] = 0;
- }
- }
-
- return 0;
-}
-#else
-#include <signal.h>
-
-static void Memento_signal(void)
-{
- globals.segv = 1;
- /* If we just return from this function the SEGV will be unhandled, and
- * we'll launch into whatever JIT debugging system the OS provides. At
- * least fprintf(stderr, something useful first. If MEMENTO_NOJIT is set, then
- * just exit to avoid the JIT (and get the usual atexit handling). */
- if (getenv("MEMENTO_NOJIT"))
- exit(1);
- else
- Memento_fin();
-}
-
-int squeeze(void)
-{
- fprintf(stderr, "Memento memory squeezing disabled as no fork!\n");
- return 0;
-}
-#endif
-
-static void Memento_startFailing(void)
-{
- if (!globals.failing) {
- fprintf(stderr, "Starting to fail...\n");
- fflush(stderr);
- globals.failing = 1;
- globals.failAt = globals.sequence;
- globals.nextFailAt = globals.sequence+1;
- globals.pattern = 0;
- globals.patternBit = 0;
- signal(SIGSEGV, Memento_signal);
- signal(SIGABRT, Memento_signal);
- Memento_breakpoint();
- }
-}
-
-static void Memento_event(void)
-{
- globals.sequence++;
- if ((globals.sequence >= globals.paranoidAt) && (globals.paranoidAt != 0)) {
- globals.paranoia = 1;
- globals.countdown = 1;
- }
- if (--globals.countdown == 0) {
- Memento_checkAllMemory();
- globals.countdown = globals.paranoia;
- }
-
- if (globals.sequence == globals.breakAt) {
- fprintf(stderr, "Breaking at event %d\n", globals.breakAt);
- Memento_breakpoint();
- }
-}
-
-int Memento_breakAt(int event)
-{
- globals.breakAt = event;
- return event;
-}
-
-void *Memento_label(void *ptr, const char *label)
-{
- Memento_BlkHeader *block;
-
- if (ptr == NULL)
- return NULL;
- block = MEMBLK_FROMBLK(ptr);
- block->label = label;
- return ptr;
-}
-
-int Memento_failThisEvent(void)
-{
- int failThisOne;
-
- if (!globals.inited)
- Memento_init();
-
- Memento_event();
-
- if ((globals.sequence >= globals.failAt) && (globals.failAt != 0))
- Memento_startFailing();
- if ((globals.sequence >= globals.squeezeAt) && (globals.squeezeAt != 0)) {
- return squeeze();
- }
-
- if (!globals.failing)
- return 0;
- failThisOne = ((globals.patternBit & globals.pattern) == 0);
- /* If we are failing, and we've reached the end of the pattern and we've
- * still got bits available in the pattern word, and we haven't already
- * set a nextPattern, then extend the pattern. */
- if (globals.failing &&
- ((~(globals.patternBit-1) & globals.pattern) == 0) &&
- (globals.patternBit != 0) &&
- globals.nextPattern == 0)
- {
- /* We'll fail this one, and set the 'next' one to pass it. */
- globals.nextFailAt = globals.failAt;
- globals.nextPattern = globals.pattern | globals.patternBit;
- }
- globals.patternBit = (globals.patternBit ? globals.patternBit << 1 : 1);
-
- return failThisOne;
-}
-
-void *Memento_malloc(size_t s)
-{
- Memento_BlkHeader *memblk;
- size_t smem = MEMBLK_SIZE(s);
-
- if (Memento_failThisEvent())
- return NULL;
-
- if (s == 0)
- return NULL;
-
- globals.numMallocs++;
-
- if (globals.maxMemory != 0 && globals.alloc + s > globals.maxMemory)
- return NULL;
-
- memblk = MEMENTO_UNDERLYING_MALLOC(smem);
- if (memblk == NULL)
- return NULL;
-
- globals.alloc += s;
- globals.totalAlloc += s;
- if (globals.peakAlloc < globals.alloc)
- globals.peakAlloc = globals.alloc;
-#ifndef MEMENTO_LEAKONLY
- memset(MEMBLK_TOBLK(memblk), MEMENTO_ALLOCFILL, s);
-#endif
- memblk->rawsize = s;
- memblk->sequence = globals.sequence;
- memblk->lastCheckedOK = memblk->sequence;
- memblk->flags = 0;
- memblk->label = 0;
- memblk->child = NULL;
- memblk->sibling = NULL;
- Memento_addBlockHead(&globals.used, memblk, 0);
- return MEMBLK_TOBLK(memblk);
-}
-
-void *Memento_calloc(size_t n, size_t s)
-{
- void *block = Memento_malloc(n*s);
-
- if (block)
- memset(block, 0, n*s);
- return block;
-}
-
-static int checkBlock(Memento_BlkHeader *memblk, const char *action)
-{
-#ifndef MEMENTO_LEAKONLY
- BlkCheckData data;
-
- memset(&data, 0, sizeof(data));
- Memento_appBlock(&globals.used, Memento_Internal_checkAllocedBlock,
- &data, memblk);
- if (!data.found) {
- /* Failure! */
- fprintf(stderr, "Attempt to %s block ", action);
- showBlock(memblk, 32);
- Memento_breakpoint();
- return 1;
- } else if (data.preCorrupt || data.postCorrupt) {
- fprintf(stderr, "Block ");
- showBlock(memblk, ' ');
- fprintf(stderr, " found to be corrupted on %s!\n", action);
- if (data.preCorrupt) {
- fprintf(stderr, "Preguard corrupted\n");
- }
- if (data.postCorrupt) {
- fprintf(stderr, "Postguard corrupted\n");
- }
- fprintf(stderr, "Block last checked OK at allocation %d. Now %d.\n",
- memblk->lastCheckedOK, globals.sequence);
- Memento_breakpoint();
- return 1;
- }
-#endif
- return 0;
-}
-
-void Memento_free(void *blk)
-{
- Memento_BlkHeader *memblk;
-
- if (!globals.inited)
- Memento_init();
-
- Memento_event();
-
- if (blk == NULL)
- return;
-
- memblk = MEMBLK_FROMBLK(blk);
- VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk));
- if (checkBlock(memblk, "free"))
- return;
-
- if (memblk->flags & Memento_Flag_BreakOnFree)
- Memento_breakpoint();
-
- VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk));
- globals.alloc -= memblk->rawsize;
- globals.numFrees++;
-
- Memento_removeBlock(&globals.used, memblk);
-
- VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk));
- if (Memento_Internal_makeSpace(MEMBLK_SIZE(memblk->rawsize))) {
- VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk));
- VALGRIND_MAKE_MEM_DEFINED(MEMBLK_TOBLK(memblk),
- memblk->rawsize + Memento_PostSize);
-#ifndef MEMENTO_LEAKONLY
- memset(MEMBLK_TOBLK(memblk), MEMENTO_FREEFILL, memblk->rawsize);
-#endif
- Memento_addBlockTail(&globals.free, memblk, 1);
- } else {
- MEMENTO_UNDERLYING_FREE(memblk);
- }
-}
-
-void *Memento_realloc(void *blk, size_t newsize)
-{
- Memento_BlkHeader *memblk, *newmemblk;
- size_t newsizemem;
- int flags;
-
- if (blk == NULL)
- return Memento_malloc(newsize);
- if (newsize == 0) {
- Memento_free(blk);
- return NULL;
- }
-
- if (Memento_failThisEvent())
- return NULL;
-
- memblk = MEMBLK_FROMBLK(blk);
- if (checkBlock(memblk, "realloc"))
- return NULL;
-
- if (memblk->flags & Memento_Flag_BreakOnRealloc)
- Memento_breakpoint();
-
- if (globals.maxMemory != 0 && globals.alloc - memblk->rawsize + newsize > globals.maxMemory)
- return NULL;
-
- newsizemem = MEMBLK_SIZE(newsize);
- Memento_removeBlock(&globals.used, memblk);
- flags = memblk->flags;
- newmemblk = MEMENTO_UNDERLYING_REALLOC(memblk, newsizemem);
- if (newmemblk == NULL)
- {
- Memento_addBlockHead(&globals.used, memblk, 2);
- return NULL;
- }
- globals.numReallocs++;
- globals.totalAlloc += newsize;
- globals.alloc -= newmemblk->rawsize;
- globals.alloc += newsize;
- if (globals.peakAlloc < globals.alloc)
- globals.peakAlloc = globals.alloc;
- newmemblk->flags = flags;
- if (newmemblk->rawsize < newsize) {
- char *newbytes = ((char *)MEMBLK_TOBLK(newmemblk))+newmemblk->rawsize;
-#ifndef MEMENTO_LEAKONLY
- memset(newbytes, MEMENTO_ALLOCFILL, newsize - newmemblk->rawsize);
-#endif
- VALGRIND_MAKE_MEM_UNDEFINED(newbytes, newsize - newmemblk->rawsize);
- }
- newmemblk->rawsize = newsize;
-#ifndef MEMENTO_LEAKONLY
- memset(newmemblk->preblk, MEMENTO_PREFILL, Memento_PreSize);
- memset(MEMBLK_POSTPTR(newmemblk), MEMENTO_POSTFILL, Memento_PostSize);
-#endif
- Memento_addBlockHead(&globals.used, newmemblk, 2);
- return MEMBLK_TOBLK(newmemblk);
-}
-
-int Memento_checkBlock(void *blk)
-{
- Memento_BlkHeader *memblk;
-
- if (blk == NULL)
- return 0;
- memblk = MEMBLK_FROMBLK(blk);
- return checkBlock(memblk, "check");
-}
-
-static int Memento_Internal_checkAllAlloced(Memento_BlkHeader *memblk, void *arg)
-{
- BlkCheckData *data = (BlkCheckData *)arg;
-
- Memento_Internal_checkAllocedBlock(memblk, data);
- if (data->preCorrupt || data->postCorrupt) {
- if ((data->found & 2) == 0) {
- fprintf(stderr, "Allocated blocks:\n");
- data->found |= 2;
- }
- fprintf(stderr, " Block ");
- showBlock(memblk, ' ');
- if (data->preCorrupt) {
- fprintf(stderr, " Preguard ");
- }
- if (data->postCorrupt) {
- fprintf(stderr, "%s Postguard ",
- (data->preCorrupt ? "&" : ""));
- }
- fprintf(stderr, "corrupted.\n "
- "Block last checked OK at allocation %d. Now %d.\n",
- memblk->lastCheckedOK, globals.sequence);
- data->preCorrupt = 0;
- data->postCorrupt = 0;
- data->freeCorrupt = 0;
- }
- else
- memblk->lastCheckedOK = globals.sequence;
- return 0;
-}
-
-static int Memento_Internal_checkAllFreed(Memento_BlkHeader *memblk, void *arg)
-{
- BlkCheckData *data = (BlkCheckData *)arg;
-
- Memento_Internal_checkFreedBlock(memblk, data);
- if (data->preCorrupt || data->postCorrupt || data->freeCorrupt) {
- if ((data->found & 4) == 0) {
- fprintf(stderr, "Freed blocks:\n");
- data->found |= 4;
- }
- fprintf(stderr, " ");
- showBlock(memblk, ' ');
- if (data->freeCorrupt) {
- fprintf(stderr, " index %d (address 0x%p) onwards", data->index,
- &((char *)MEMBLK_TOBLK(memblk))[data->index]);
- if (data->preCorrupt) {
- fprintf(stderr, "+ preguard");
- }
- if (data->postCorrupt) {
- fprintf(stderr, "+ postguard");
- }
- } else {
- if (data->preCorrupt) {
- fprintf(stderr, " preguard");
- }
- if (data->postCorrupt) {
- fprintf(stderr, "%s Postguard",
- (data->preCorrupt ? "+" : ""));
- }
- }
- fprintf(stderr, " corrupted.\n"
- " Block last checked OK at allocation %d. Now %d.\n",
- memblk->lastCheckedOK, globals.sequence);
- data->preCorrupt = 0;
- data->postCorrupt = 0;
- data->freeCorrupt = 0;
- }
- else
- memblk->lastCheckedOK = globals.sequence;
- return 0;
-}
-
-int Memento_checkAllMemory(void)
-{
-#ifndef MEMENTO_LEAKONLY
- BlkCheckData data;
-
- memset(&data, 0, sizeof(data));
- Memento_appBlocks(&globals.used, Memento_Internal_checkAllAlloced, &data);
- Memento_appBlocks(&globals.free, Memento_Internal_checkAllFreed, &data);
- if (data.found & 6) {
- Memento_breakpoint();
- return 1;
- }
-#endif
- return 0;
-}
-
-int Memento_setParanoia(int i)
-{
- globals.paranoia = i;
- globals.countdown = globals.paranoia;
- return i;
-}
-
-int Memento_paranoidAt(int i)
-{
- globals.paranoidAt = i;
- return i;
-}
-
-int Memento_getBlockNum(void *b)
-{
- Memento_BlkHeader *memblk;
- if (b == NULL)
- return 0;
- memblk = MEMBLK_FROMBLK(b);
- return (memblk->sequence);
-}
-
-int Memento_check(void)
-{
- int result;
-
- fprintf(stderr, "Checking memory\n");
- result = Memento_checkAllMemory();
- fprintf(stderr, "Memory checked!\n");
- return result;
-}
-
-typedef struct findBlkData {
- void *addr;
- Memento_BlkHeader *blk;
- int flags;
-} findBlkData;
-
-static int Memento_containsAddr(Memento_BlkHeader *b,
- void *arg)
-{
- findBlkData *data = (findBlkData *)arg;
- char *blkend = &((char *)MEMBLK_TOBLK(b))[b->rawsize];
- if ((MEMBLK_TOBLK(b) <= data->addr) &&
- ((void *)blkend > data->addr)) {
- data->blk = b;
- data->flags = 1;
- return 1;
- }
- if (((void *)b <= data->addr) &&
- (MEMBLK_TOBLK(b) > data->addr)) {
- data->blk = b;
- data->flags = 2;
- return 1;
- }
- if (((void *)blkend <= data->addr) &&
- ((void *)(blkend + Memento_PostSize) > data->addr)) {
- data->blk = b;
- data->flags = 3;
- return 1;
- }
- return 0;
-}
-
-int Memento_find(void *a)
-{
- findBlkData data;
-
- data.addr = a;
- data.blk = NULL;
- data.flags = 0;
- Memento_appBlocks(&globals.used, Memento_containsAddr, &data);
- if (data.blk != NULL) {
- fprintf(stderr, "Address 0x%p is in %sallocated block ",
- data.addr,
- (data.flags == 1 ? "" : (data.flags == 2 ?
- "preguard of " : "postguard of ")));
- showBlock(data.blk, ' ');
- fprintf(stderr, "\n");
- return data.blk->sequence;
- }
- data.blk = NULL;
- data.flags = 0;
- Memento_appBlocks(&globals.free, Memento_containsAddr, &data);
- if (data.blk != NULL) {
- fprintf(stderr, "Address 0x%p is in %sfreed block ",
- data.addr,
- (data.flags == 1 ? "" : (data.flags == 2 ?
- "preguard of " : "postguard of ")));
- showBlock(data.blk, ' ');
- fprintf(stderr, "\n");
- return data.blk->sequence;
- }
- return 0;
-}
-
-void Memento_breakOnFree(void *a)
-{
- findBlkData data;
-
- data.addr = a;
- data.blk = NULL;
- data.flags = 0;
- Memento_appBlocks(&globals.used, Memento_containsAddr, &data);
- if (data.blk != NULL) {
- fprintf(stderr, "Will stop when address 0x%p (in %sallocated block ",
- data.addr,
- (data.flags == 1 ? "" : (data.flags == 2 ?
- "preguard of " : "postguard of ")));
- showBlock(data.blk, ' ');
- fprintf(stderr, ") is freed\n");
- data.blk->flags |= Memento_Flag_BreakOnFree;
- return;
- }
- data.blk = NULL;
- data.flags = 0;
- Memento_appBlocks(&globals.free, Memento_containsAddr, &data);
- if (data.blk != NULL) {
- fprintf(stderr, "Can't stop on free; address 0x%p is in %sfreed block ",
- data.addr,
- (data.flags == 1 ? "" : (data.flags == 2 ?
- "preguard of " : "postguard of ")));
- showBlock(data.blk, ' ');
- fprintf(stderr, "\n");
- return;
- }
- fprintf(stderr, "Can't stop on free; address 0x%p is not in a known block.\n", a);
-}
-
-void Memento_breakOnRealloc(void *a)
-{
- findBlkData data;
-
- data.addr = a;
- data.blk = NULL;
- data.flags = 0;
- Memento_appBlocks(&globals.used, Memento_containsAddr, &data);
- if (data.blk != NULL) {
- fprintf(stderr, "Will stop when address 0x%p (in %sallocated block ",
- data.addr,
- (data.flags == 1 ? "" : (data.flags == 2 ?
- "preguard of " : "postguard of ")));
- showBlock(data.blk, ' ');
- fprintf(stderr, ") is freed (or realloced)\n");
- data.blk->flags |= Memento_Flag_BreakOnFree | Memento_Flag_BreakOnRealloc;
- return;
- }
- data.blk = NULL;
- data.flags = 0;
- Memento_appBlocks(&globals.free, Memento_containsAddr, &data);
- if (data.blk != NULL) {
- fprintf(stderr, "Can't stop on free/realloc; address 0x%p is in %sfreed block ",
- data.addr,
- (data.flags == 1 ? "" : (data.flags == 2 ?
- "preguard of " : "postguard of ")));
- showBlock(data.blk, ' ');
- fprintf(stderr, "\n");
- return;
- }
- fprintf(stderr, "Can't stop on free/realloc; address 0x%p is not in a known block.\n", a);
-}
-
-int Memento_failAt(int i)
-{
- globals.failAt = i;
- if ((globals.sequence > globals.failAt) &&
- (globals.failing != 0))
- Memento_startFailing();
- return i;
-}
-
-size_t Memento_setMax(size_t max)
-{
- globals.maxMemory = max;
- return max;
-}
-
-#else
-
-/* Just in case anyone has left some debugging code in... */
-void (Memento_breakpoint)(void)
-{
-}
-
-int (Memento_checkBlock)(void *b)
-{
- return 0;
-}
-
-int (Memento_checkAllMemory)(void)
-{
- return 0;
-}
-
-int (Memento_check)(void)
-{
- return 0;
-}
-
-int (Memento_setParanoia)(int i)
-{
- return 0;
-}
-
-int (Memento_paranoidAt)(int i)
-{
- return 0;
-}
-
-int (Memento_breakAt)(int i)
-{
- return 0;
-}
-
-int (Memento_getBlockNum)(void *i)
-{
- return 0;
-}
-
-int (Memento_find)(void *a)
-{
- return 0;
-}
-
-int (Memento_failAt)(int i)
-{
- return 0;
-}
-
-void (Memento_breakOnFree)(void *a)
-{
-}
-
-void (Memento_breakOnRealloc)(void *a)
-{
-}
-
-#undef Memento_malloc
-#undef Memento_free
-#undef Memento_realloc
-#undef Memento_calloc
-
-void *Memento_malloc(size_t size)
-{
- return MEMENTO_UNDERLYING_MALLOC(size);
-}
-
-void Memento_free(void *b)
-{
- MEMENTO_UNDERLYING_FREE(b);
-}
-
-void *Memento_realloc(void *b, size_t s)
-{
- return MEMENTO_UNDERLYING_REALLOC(b, s);
-}
-
-void *Memento_calloc(size_t n, size_t s)
-{
- return MEMENTO_UNDERLYING_CALLOC(n, s);
-}
-
-void (Memento_listBlocks)(void)
-{
-}
-
-void (Memento_listNewBlocks)(void)
-{
-}
-
-size_t (Memento_setMax)(size_t max)
-{
- return 0;
-}
-
-void (Memento_stats)(void)
-{
-}
-
-void *(Memento_label)(void *ptr, const char *label)
-{
- return ptr;
-}
-
-#endif
diff --git a/fitz/res_bitmap.c b/fitz/res_bitmap.c
deleted file mode 100644
index 6357f7d7..00000000
--- a/fitz/res_bitmap.c
+++ /dev/null
@@ -1,123 +0,0 @@
-#include "mupdf/fitz.h"
-
-fz_bitmap *
-fz_new_bitmap(fz_context *ctx, int w, int h, int n, int xres, int yres)
-{
- fz_bitmap *bit;
-
- bit = fz_malloc_struct(ctx, fz_bitmap);
- bit->refs = 1;
- bit->w = w;
- bit->h = h;
- bit->n = n;
- bit->xres = xres;
- bit->yres = yres;
- /* Span is 32 bit aligned. We may want to make this 64 bit if we
- * use SSE2 etc. */
- bit->stride = ((n * w + 31) & ~31) >> 3;
-
- bit->samples = fz_malloc_array(ctx, h, bit->stride);
-
- return bit;
-}
-
-fz_bitmap *
-fz_keep_bitmap(fz_context *ctx, fz_bitmap *bit)
-{
- if (bit)
- bit->refs++;
- return bit;
-}
-
-void
-fz_drop_bitmap(fz_context *ctx, fz_bitmap *bit)
-{
- if (bit && --bit->refs == 0)
- {
- fz_free(ctx, bit->samples);
- fz_free(ctx, bit);
- }
-}
-
-void
-fz_clear_bitmap(fz_context *ctx, fz_bitmap *bit)
-{
- memset(bit->samples, 0, bit->stride * bit->h);
-}
-
-/*
- * Write bitmap to PBM file
- */
-
-void
-fz_write_pbm(fz_context *ctx, fz_bitmap *bitmap, char *filename)
-{
- FILE *fp;
- unsigned char *p;
- int h, bytestride;
-
- fp = fopen(filename, "wb");
- if (!fp)
- fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open file '%s': %s", filename, strerror(errno));
-
- assert(bitmap->n == 1);
-
- fprintf(fp, "P4\n%d %d\n", bitmap->w, bitmap->h);
-
- p = bitmap->samples;
-
- h = bitmap->h;
- bytestride = (bitmap->w + 7) >> 3;
- while (h--)
- {
- fwrite(p, 1, bytestride, fp);
- p += bitmap->stride;
- }
-
- 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_samples(fz_context *ctx, fz_pixmap *pix)
-{
- if (!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)
- *stride = bit->stride;
-}
diff --git a/fitz/res_colorspace.c b/fitz/res_colorspace.c
deleted file mode 100644
index 07da5a95..00000000
--- a/fitz/res_colorspace.c
+++ /dev/null
@@ -1,1277 +0,0 @@
-#include "mupdf/fitz.h"
-
-#define SLOWCMYK
-
-void
-fz_free_colorspace_imp(fz_context *ctx, fz_storable *cs_)
-{
- fz_colorspace *cs = (fz_colorspace *)cs_;
-
- if (cs->free_data && cs->data)
- cs->free_data(ctx, cs);
- fz_free(ctx, cs);
-}
-
-fz_colorspace *
-fz_new_colorspace(fz_context *ctx, char *name, int n)
-{
- fz_colorspace *cs = fz_malloc(ctx, sizeof(fz_colorspace));
- FZ_INIT_STORABLE(cs, 1, fz_free_colorspace_imp);
- cs->size = sizeof(fz_colorspace);
- fz_strlcpy(cs->name, name, sizeof cs->name);
- cs->n = n;
- cs->to_rgb = NULL;
- cs->from_rgb = NULL;
- cs->free_data = NULL;
- cs->data = NULL;
- return cs;
-}
-
-fz_colorspace *
-fz_keep_colorspace(fz_context *ctx, fz_colorspace *cs)
-{
- return (fz_colorspace *)fz_keep_storable(ctx, &cs->storable);
-}
-
-void
-fz_drop_colorspace(fz_context *ctx, fz_colorspace *cs)
-{
- fz_drop_storable(ctx, &cs->storable);
-}
-
-/* Device colorspace definitions */
-
-static void gray_to_rgb(fz_context *ctx, fz_colorspace *cs, float *gray, float *rgb)
-{
- rgb[0] = gray[0];
- rgb[1] = gray[0];
- rgb[2] = gray[0];
-}
-
-static void rgb_to_gray(fz_context *ctx, fz_colorspace *cs, float *rgb, float *gray)
-{
- float r = rgb[0];
- float g = rgb[1];
- float b = rgb[2];
- gray[0] = r * 0.3f + g * 0.59f + b * 0.11f;
-}
-
-static void rgb_to_rgb(fz_context *ctx, fz_colorspace *cs, float *rgb, float *xyz)
-{
- xyz[0] = rgb[0];
- xyz[1] = rgb[1];
- xyz[2] = rgb[2];
-}
-
-static void bgr_to_rgb(fz_context *ctx, fz_colorspace *cs, float *bgr, float *rgb)
-{
- rgb[0] = bgr[2];
- rgb[1] = bgr[1];
- rgb[2] = bgr[0];
-}
-
-static void rgb_to_bgr(fz_context *ctx, fz_colorspace *cs, float *rgb, float *bgr)
-{
- bgr[0] = rgb[2];
- bgr[1] = rgb[1];
- bgr[2] = rgb[0];
-}
-
-static void cmyk_to_rgb(fz_context *ctx, fz_colorspace *cs, float *cmyk, float *rgb)
-{
-#ifdef SLOWCMYK /* from poppler */
- float c = cmyk[0], m = cmyk[1], y = cmyk[2], k = cmyk[3];
- float r, g, b, x;
- float cm = c * m;
- float c1m = m - cm;
- float cm1 = c - cm;
- float c1m1 = 1 - m - cm1;
- float c1m1y = c1m1 * y;
- float c1m1y1 = c1m1 - c1m1y;
- float c1my = c1m * y;
- float c1my1 = c1m - c1my;
- float cm1y = cm1 * y;
- float cm1y1 = cm1 - cm1y;
- float cmy = cm * y;
- float cmy1 = cm - cmy;
-
- /* this is a matrix multiplication, unrolled for performance */
- x = c1m1y1 * k; /* 0 0 0 1 */
- r = g = b = c1m1y1 - x; /* 0 0 0 0 */
- r += 0.1373 * x;
- g += 0.1216 * x;
- b += 0.1255 * x;
-
- x = c1m1y * k; /* 0 0 1 1 */
- r += 0.1098 * x;
- g += 0.1020 * x;
- x = c1m1y - x; /* 0 0 1 0 */
- r += x;
- g += 0.9490 * x;
-
- x = c1my1 * k; /* 0 1 0 1 */
- r += 0.1412 * x;
- x = c1my1 - x; /* 0 1 0 0 */
- r += 0.9255 * x;
- b += 0.5490 * x;
-
- x = c1my * k; /* 0 1 1 1 */
- r += 0.1333 * x;
- x = c1my - x; /* 0 1 1 0 */
- r += 0.9294 * x;
- g += 0.1098 * x;
- b += 0.1412 * x;
-
- x = cm1y1 * k; /* 1 0 0 1 */
- g += 0.0588 * x;
- b += 0.1412 * x;
- x = cm1y1 - x; /* 1 0 0 0 */
- g += 0.6784 * x;
- b += 0.9373 * x;
-
- x = cm1y * k; /* 1 0 1 1 */
- g += 0.0745 * x;
- x = cm1y - x; /* 1 0 1 0 */
- g += 0.6510 * x;
- b += 0.3137 * x;
-
- x = cmy1 * k; /* 1 1 0 1 */
- b += 0.0078 * x;
- x = cmy1 - x; /* 1 1 0 0 */
- r += 0.1804 * x;
- g += 0.1922 * x;
- b += 0.5725 * x;
-
- x = cmy * (1-k); /* 1 1 1 0 */
- r += 0.2118 * x;
- g += 0.2119 * x;
- b += 0.2235 * x;
- rgb[0] = fz_clamp(r, 0, 1);
- rgb[1] = fz_clamp(g, 0, 1);
- rgb[2] = fz_clamp(b, 0, 1);
-#else
- rgb[0] = 1 - fz_min(1, cmyk[0] + cmyk[3]);
- rgb[1] = 1 - fz_min(1, cmyk[1] + cmyk[3]);
- rgb[2] = 1 - fz_min(1, cmyk[2] + cmyk[3]);
-#endif
-}
-
-static void rgb_to_cmyk(fz_context *ctx, fz_colorspace *cs, float *rgb, float *cmyk)
-{
- float c, m, y, k;
- c = 1 - rgb[0];
- m = 1 - rgb[1];
- y = 1 - rgb[2];
- k = fz_min(c, fz_min(m, y));
- cmyk[0] = c - k;
- cmyk[1] = m - k;
- cmyk[2] = y - k;
- cmyk[3] = k;
-}
-
-static fz_colorspace k_default_gray = { {-1, fz_free_colorspace_imp}, 0, "DeviceGray", 1, gray_to_rgb, rgb_to_gray };
-static fz_colorspace k_default_rgb = { {-1, fz_free_colorspace_imp}, 0, "DeviceRGB", 3, rgb_to_rgb, rgb_to_rgb };
-static fz_colorspace k_default_bgr = { {-1, fz_free_colorspace_imp}, 0, "DeviceRGB", 3, bgr_to_rgb, rgb_to_bgr };
-static fz_colorspace k_default_cmyk = { {-1, fz_free_colorspace_imp}, 0, "DeviceCMYK", 4, cmyk_to_rgb, rgb_to_cmyk };
-
-static fz_colorspace *fz_default_gray = &k_default_gray;
-static fz_colorspace *fz_default_rgb = &k_default_rgb;
-static fz_colorspace *fz_default_bgr = &k_default_bgr;
-static fz_colorspace *fz_default_cmyk = &k_default_cmyk;
-
-struct fz_colorspace_context_s
-{
- int ctx_refs;
- fz_colorspace *gray, *rgb, *bgr, *cmyk;
-};
-
-void fz_new_colorspace_context(fz_context *ctx)
-{
- ctx->colorspace = fz_malloc_struct(ctx, fz_colorspace_context);
- ctx->colorspace->ctx_refs = 1;
- ctx->colorspace->gray = fz_default_gray;
- ctx->colorspace->rgb = fz_default_rgb;
- ctx->colorspace->bgr = fz_default_bgr;
- ctx->colorspace->cmyk = fz_default_cmyk;
-}
-
-fz_colorspace_context *
-fz_keep_colorspace_context(fz_context *ctx)
-{
- if (!ctx || !ctx->colorspace)
- return NULL;
- fz_lock(ctx, FZ_LOCK_ALLOC);
- ctx->colorspace->ctx_refs++;
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- return ctx->colorspace;
-}
-
-void fz_drop_colorspace_context(fz_context *ctx)
-{
- int drop;
- if (!ctx || !ctx->colorspace)
- return;
- fz_lock(ctx, FZ_LOCK_ALLOC);
- drop = --ctx->colorspace->ctx_refs;
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- if (drop == 0)
- fz_free(ctx, ctx->colorspace);
-}
-
-fz_colorspace *
-fz_device_gray(fz_context *ctx)
-{
- return ctx->colorspace->gray;
-}
-
-fz_colorspace *
-fz_device_rgb(fz_context *ctx)
-{
- return ctx->colorspace->rgb;
-}
-
-fz_colorspace *
-fz_device_bgr(fz_context *ctx)
-{
- return ctx->colorspace->bgr;
-}
-
-fz_colorspace *
-fz_device_cmyk(fz_context *ctx)
-{
- return ctx->colorspace->cmyk;
-}
-
-fz_colorspace *
-fz_lookup_device_colorspace(fz_context *ctx, char *name)
-{
- if (!strcmp(name, "DeviceGray"))
- return fz_device_gray(ctx);
- if (!strcmp(name, "DeviceRGB"))
- return fz_device_rgb(ctx);
- if (!strcmp(name, "DeviceBGR"))
- return fz_device_bgr(ctx);
- if (!strcmp(name, "DeviceCMYK"))
- return fz_device_cmyk(ctx);
- assert(!"unknown device colorspace");
- return NULL;
-}
-
-void
-fz_set_device_gray(fz_context *ctx, fz_colorspace *cs)
-{
- fz_drop_colorspace(ctx, ctx->colorspace->gray);
- ctx->colorspace->gray = fz_keep_colorspace(ctx, cs);
-}
-
-void
-fz_set_device_rgb(fz_context *ctx, fz_colorspace *cs)
-{
- fz_drop_colorspace(ctx, ctx->colorspace->rgb);
- ctx->colorspace->rgb = fz_keep_colorspace(ctx, cs);
-}
-
-void
-fz_set_device_bgr(fz_context *ctx, fz_colorspace *cs)
-{
- fz_drop_colorspace(ctx, ctx->colorspace->bgr);
- ctx->colorspace->bgr = fz_keep_colorspace(ctx, cs);
-}
-
-void
-fz_set_device_cmyk(fz_context *ctx, fz_colorspace *cs)
-{
- fz_drop_colorspace(ctx, ctx->colorspace->cmyk);
- ctx->colorspace->cmyk = fz_keep_colorspace(ctx, cs);
-}
-
-int
-fz_colorspace_is_indexed(fz_colorspace *cs)
-{
- return (cs && !strcmp(cs->name, "Indexed"));
-}
-
-/* Fast pixmap color conversions */
-
-static void fast_gray_to_rgb(fz_pixmap *dst, fz_pixmap *src)
-{
- unsigned char *s = src->samples;
- unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
- {
- d[0] = s[0];
- d[1] = s[0];
- d[2] = s[0];
- d[3] = s[1];
- s += 2;
- d += 4;
- }
-}
-
-static void fast_gray_to_cmyk(fz_pixmap *dst, fz_pixmap *src)
-{
- unsigned char *s = src->samples;
- unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
- {
- d[0] = 0;
- d[1] = 0;
- d[2] = 0;
- d[3] = s[0];
- d[4] = s[1];
- s += 2;
- d += 5;
- }
-}
-
-static void fast_rgb_to_gray(fz_pixmap *dst, fz_pixmap *src)
-{
- unsigned char *s = src->samples;
- unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
- {
- d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8;
- d[1] = s[3];
- s += 4;
- d += 2;
- }
-}
-
-static void fast_bgr_to_gray(fz_pixmap *dst, fz_pixmap *src)
-{
- unsigned char *s = src->samples;
- unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
- {
- d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8;
- d[1] = s[3];
- s += 4;
- d += 2;
- }
-}
-
-static void fast_rgb_to_cmyk(fz_pixmap *dst, fz_pixmap *src)
-{
- unsigned char *s = src->samples;
- unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
- {
- unsigned char c = 255 - s[0];
- unsigned char m = 255 - s[1];
- unsigned char y = 255 - s[2];
- unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
- d[0] = c - k;
- d[1] = m - k;
- d[2] = y - k;
- d[3] = k;
- d[4] = s[3];
- s += 4;
- d += 5;
- }
-}
-
-static void fast_bgr_to_cmyk(fz_pixmap *dst, fz_pixmap *src)
-{
- unsigned char *s = src->samples;
- unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
- {
- unsigned char c = 255 - s[2];
- unsigned char m = 255 - s[1];
- unsigned char y = 255 - s[0];
- unsigned char k = (unsigned char)fz_mini(c, fz_mini(m, y));
- d[0] = c - k;
- d[1] = m - k;
- d[2] = y - k;
- d[3] = k;
- d[4] = s[3];
- s += 4;
- d += 5;
- }
-}
-
-static void fast_cmyk_to_gray(fz_pixmap *dst, fz_pixmap *src)
-{
- unsigned char *s = src->samples;
- unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
- {
- unsigned char c = fz_mul255(s[0], 77);
- unsigned char m = fz_mul255(s[1], 150);
- unsigned char y = fz_mul255(s[2], 28);
- d[0] = 255 - (unsigned char)fz_mini(c + m + y + s[3], 255);
- d[1] = s[4];
- s += 5;
- d += 2;
- }
-}
-
-#ifdef ARCH_ARM
-static void
-fast_cmyk_to_rgb_ARM(unsigned char *dst, unsigned char *src, int n)
-__attribute__((naked));
-
-static void
-fast_cmyk_to_rgb_ARM(unsigned char *dst, unsigned char *src, int n)
-{
- asm volatile(
- ENTER_ARM
- "stmfd r13!,{r4-r11,r14} \n"
- "@ r0 = dst \n"
- "@ r1 = src \n"
- "@ r2 = n \n"
- "mov r12, #0 @ r12= CMYK = 0 \n"
- "b 2f @ enter loop \n"
- "1: @ White or Black \n"
- "@ Cunning trick: On entry r11 = 0 if black, r11 = FF if white \n"
- "ldrb r7, [r1],#1 @ r8 = s[4] \n"
- "strb r11,[r0],#1 @ d[0] = r \n"
- "strb r11,[r0],#1 @ d[1] = g \n"
- "strb r11,[r0],#1 @ d[2] = b \n"
- "strb r7, [r0],#1 @ d[3] = s[4] \n"
- "subs r2, r2, #1 @ r2 = n-- \n"
- "beq 9f \n"
- "2: @ Main loop starts here \n"
- "ldrb r3, [r1], #4 @ r3 = c \n"
- "ldrb r6, [r1, #-1] @ r6 = k \n"
- "ldrb r5, [r1, #-2] @ r5 = y \n"
- "ldrb r4, [r1, #-3] @ r4 = m \n"
- "eors r11,r6, #0xFF @ if (k == 255) \n"
- "beq 1b @ goto black \n"
- "orr r7, r3, r4, LSL #8 \n"
- "orr r14,r5, r6, LSL #8 \n"
- "orrs r7, r7, r14,LSL #16 @ r7 = cmyk \n"
- "beq 1b @ if (cmyk == 0) white \n"
- "@ At this point, we have to decode a new pixel \n"
- "@ r0 = dst r1 = src r2 = n r7 = cmyk \n"
- "3: @ unmatched \n"
- "stmfd r13!,{r0-r1,r7} @ stash regs for space \n"
- "add r3, r3, r3, LSR #7 @ r3 = c += c>>7 \n"
- "add r4, r4, r4, LSR #7 @ r4 = m += m>>7 \n"
- "add r5, r5, r5, LSR #7 @ r5 = y += y>>7 \n"
- "add r6, r6, r6, LSR #7 @ r6 = k += k>>7 \n"
- "mov r5, r5, LSR #1 @ sacrifice 1 bit of Y \n"
- "mul r8, r3, r4 @ r8 = cm = c * m \n"
- "rsb r9, r8, r4, LSL #8 @ r9 = c1m = (m<<8) - cm \n"
- "rsb r3, r8, r3, LSL #8 @ r3 = cm1 = (c<<8) - cm \n"
- "rsb r4, r4, #0x100 @ r4 = 256-m \n"
- "rsb r4, r3, r4, LSL #8 @ r4 = c1m1 =((256-m)<<8)-cm1 \n"
- "mul r7, r4, r5 @ r7 = c1m1y = c1m1 * y \n"
- "rsb r4, r7, r4, LSL #7 @ r4 = c1m1y1 = (c1m1<<7)-c1m1y \n"
- "mul r10,r9, r5 @ r10= c1my = c1m * y \n"
- "rsb r9, r10,r9, LSL #7 @ r9 = c1my1 = (c1m<<7) - c1my \n"
- "mul r11,r3, r5 @ r11= cm1y = cm1 * y \n"
- "rsb r3, r11,r3, LSL #7 @ r3 = cm1y1 = (cm1<<7) - cm1y \n"
- "mul r5, r8, r5 @ r5 = cmy = cm * y \n"
- "rsb r8, r5, r8, LSL #7 @ r8 = cmy1 = (cm<<7) - cmy \n"
- "@ Register recap: \n"
- "@ r3 = cm1y1 \n"
- "@ r4 = c1m1y1 \n"
- "@ r5 = cmy \n"
- "@ r6 = k \n"
- "@ r7 = c1m1y \n"
- "@ r8 = cmy1 \n"
- "@ r9 = c1my1 \n"
- "@ r10= c1my \n"
- "@ r11= cm1y \n"
- "@ The actual matrix multiplication \n"
- "mul r14,r4, r6 @ r14= x1 = c1m1y1 * k \n"
- "rsb r4, r14,r4, LSL #8 @ r4 = x0 = (c1m1y1<<8) - x1 \n"
- "add r4, r4, r14,LSR #8-5 @ r4 = b = x0 + 32*(x1>>8) \n"
- "sub r1, r4, r14,LSR #8 @ r1 = g = x0 + 31*(x1>>8) \n"
- "add r0, r1, r14,LSR #8-2 @ r0 = r = x0 + 35*(x1>>8) \n"
- " \n"
- "mul r14,r7, r6 @ r14= x1 = c1m1y * k \n"
- "rsb r7, r14,r7, LSL #8 @ r7 = x0 = (c1m1y<<8) - x1 \n"
- "add r0, r0, r7 @ r0 = r += x0 \n"
- "add r1, r1, r7 @ r1 = g += (x0>>8 * 256) \n"
- "sub r1, r1, r7, LSR #8-3 @ 248 \n"
- "sub r1, r1, r7, LSR #8-2 @ 244 \n"
- "sub r1, r1, r7, LSR #8 @ 243 \n"
- "sub r7, r14,r14,LSR #3 @ r7 = 28*(x1>>5) \n"
- "add r0, r0, r7, LSR #8-5 @ r0 = r += 28 * x1 \n"
- "sub r7, r7, r14,LSR #4 @ r7 = 26*(x1>>5) \n"
- "add r1, r1, r7, LSR #8-5 @ r1 = g += 26 * x1 \n"
- " \n"
- "mul r14,r9, r6 @ r14= x1 = c1my1 * k \n"
- "sub r9, r9, r14,LSR #8 @ r9 = x0>>8 = c1my1 - (x1>>8) \n"
- "add r0, r0, r14,LSR #8-5 @ r0 = r += (x1>>8)*32 \n"
- "add r0, r0, r14,LSR #8-2 @ r0 = r += (x1>>8)*36 \n"
- "mov r14,#237 @ r14= 237 \n"
- "mla r0,r14,r9,r0 @ r14= r += x0*237 \n"
- "mov r14,#141 @ r14= 141 \n"
- "mla r4,r14,r9,r4 @ r14= b += x0*141 \n"
- " \n"
- "mul r14,r10,r6 @ r14= x1 = c1my * k \n"
- "sub r10,r10,r14,LSR #8 @ r10= x0>>8 = c1my - (x1>>8) \n"
- "add r0, r0, r14,LSR #8-5 @ r0 = r += 32 * x1 \n"
- "add r0, r0, r14,LSR #8-1 @ r0 = r += 34 * x1 \n"
- "mov r14,#238 @ r14= 238 \n"
- "mla r0,r14,r10,r0 @ r0 = r += 238 * x0 \n"
- "mov r14,#28 @ r14= 28 \n"
- "mla r1,r14,r10,r1 @ r1 = g += 28 * x0 \n"
- "mov r14,#36 @ r14= 36 \n"
- "mla r4,r14,r10,r4 @ r4 = b += 36 * x0 \n"
- " \n"
- "mul r14,r3, r6 @ r14= x1 = cm1y1 * k \n"
- "sub r3, r3, r14,LSR #8 @ r3 = x1>>8 = cm1y1 - (x1>>8) \n"
- "add r1, r1, r14,LSR #8-4 @ r1 = g += 16*x1 \n"
- "sub r1, r1, r14,LSR #8 @ 15*x1 \n"
- "add r4, r4, r14,LSR #8-5 @ r4 = b += 32*x1 \n"
- "add r4, r4, r14,LSR #8-2 @ 36*x1 \n"
- "mov r14,#174 @ r14= 174 \n"
- "mla r1, r14,r3, r1 @ r1 = g += 174 * x0 \n"
- "mov r14,#240 @ r14= 240 \n"
- "mla r4, r14,r3, r4 @ r4 = b += 240 * x0 \n"
- " \n"
- "mul r14,r11,r6 @ r14= x1 = cm1y * k \n"
- "sub r11,r11,r14,LSR #8 @ r11= x0>>8 = cm1y - (x1>>8) \n"
- "add r1, r1, r14,LSR #8-4 @ r1 = g += x1 * 16 \n"
- "add r1, r1, r14,LSR #8 @ x1 * 17 \n"
- "add r1, r1, r14,LSR #8-1 @ x1 * 19 \n"
- "mov r14,#167 @ r14 = 167 \n"
- "mla r1, r14,r11,r1 @ r1 = g += 167 * x0 \n"
- "mov r14,#80 @ r14 = 80 \n"
- "mla r4, r14,r11,r4 @ r4 = b += 80 * x0 \n"
- " \n"
- "mul r14,r8, r6 @ r14= x1 = cmy1 * k \n"
- "sub r8, r8, r14,LSR #8 @ r8 = x0>>8 = cmy1 - (x1>>8) \n"
- "add r4, r4, r14,LSR #8-1 @ r4 = b += x1 * 2 \n"
- "mov r14,#46 @ r14=46 \n"
- "mla r0, r14,r8, r0 @ r0 = r += 46 * x0 \n"
- "mov r14,#49 @ r14=49 \n"
- "mla r1, r14,r8, r1 @ r1 = g += 49 * x0 \n"
- "mov r14,#147 @ r14=147 \n"
- "mla r4, r14,r8, r4 @ r4 = b += 147 * x0 \n"
- " \n"
- "rsb r6, r6, #256 @ r6 = k = 256-k \n"
- "mul r14,r5, r6 @ r14= x0 = cmy * (256-k) \n"
- "mov r11,#54 @ r11= 54 \n"
- "mov r14,r14,LSR #8 @ r14= (x0>>8) \n"
- "mov r8,#57 @ r8 = 57 \n"
- "mla r0,r14,r11,r0 @ r0 = r += 54*x0 \n"
- "mla r1,r14,r11,r1 @ r1 = g += 54*x0 \n"
- "mla r4,r14,r8, r4 @ r4 = b += 57*x0 \n"
- " \n"
- "sub r8, r0, r0, LSR #8 @ r8 = r -= (r>>8) \n"
- "sub r9, r1, r1, LSR #8 @ r9 = g -= (r>>8) \n"
- "sub r10,r4, r4, LSR #8 @ r10= b -= (r>>8) \n"
- "ldmfd r13!,{r0-r1,r12} \n"
- "mov r8, r8, LSR #23 @ r8 = r>>23 \n"
- "mov r9, r9, LSR #23 @ r9 = g>>23 \n"
- "mov r10,r10,LSR #23 @ r10= b>>23 \n"
- "ldrb r14,[r1],#1 @ r8 = s[4] \n"
- "strb r8, [r0],#1 @ d[0] = r \n"
- "strb r9, [r0],#1 @ d[1] = g \n"
- "strb r10,[r0],#1 @ d[2] = b \n"
- "strb r14,[r0],#1 @ d[3] = s[4] \n"
- "subs r2, r2, #1 @ r2 = n-- \n"
- "beq 9f \n"
- "@ At this point, we've just decoded a pixel \n"
- "@ r0 = dst r1 = src r2 = n r8 = r r9 = g r10= b r12= CMYK \n"
- "4: \n"
- "ldrb r3, [r1], #4 @ r3 = c \n"
- "ldrb r6, [r1, #-1] @ r6 = k \n"
- "ldrb r5, [r1, #-2] @ r5 = y \n"
- "ldrb r4, [r1, #-3] @ r4 = m \n"
- "eors r11,r6, #0xFF @ if (k == 255) \n"
- "beq 1b @ goto black \n"
- "orr r7, r3, r4, LSL #8 \n"
- "orr r14,r5, r6, LSL #8 \n"
- "orrs r7, r7, r14,LSL #16 @ r7 = cmyk \n"
- "beq 1b @ if (cmyk == 0) white \n"
- "cmp r7, r12 @ if (cmyk != CMYK) \n"
- "bne 3b @ not the same, loop \n"
- "@ If we get here, we just matched a pixel we have just decoded \n"
- "ldrb r3, [r1],#1 @ r8 = s[4] \n"
- "strb r8, [r0],#1 @ d[0] = r \n"
- "strb r9, [r0],#1 @ d[1] = g \n"
- "strb r10,[r0],#1 @ d[2] = b \n"
- "strb r3, [r0],#1 @ d[3] = s[4] \n"
- "subs r2, r2, #1 @ r2 = n-- \n"
- "bne 4b \n"
- "9: \n"
- "ldmfd r13!,{r4-r11,PC} @ pop, return to thumb \n"
- ENTER_THUMB
- );
-}
-#endif
-
-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;
- int n = src->w * src->h;
-#ifdef ARCH_ARM
- fast_cmyk_to_rgb_ARM(d, s, n);
-#else
- unsigned int C,M,Y,K,r,g,b;
-
- C = 0;
- M = 0;
- Y = 0;
- K = 0;
- r = 255;
- g = 255;
- b = 255;
-
- while (n--)
- {
-#ifdef SLOWCMYK
- unsigned int c = s[0];
- unsigned int m = s[1];
- unsigned int y = s[2];
- unsigned int k = s[3];
- unsigned int cm, c1m, cm1, c1m1, c1m1y, c1m1y1, c1my, c1my1, cm1y, cm1y1, cmy, cmy1;
- unsigned int x0, x1;
-
- if (c == C && m == M && y == Y && k == K)
- {
- /* Nothing to do */
- }
- else if (k == 0 && c == 0 && m == 0 && y == 0)
- {
- r = g = b = 255;
- }
- else if (k == 255)
- {
- r = g = b = 0;
- }
- else
- {
- c += c>>7;
- m += m>>7;
- y += y>>7;
- k += k>>7;
- y >>= 1; /* Ditch 1 bit of Y to avoid overflow */
- cm = c * m;
- c1m = (m<<8) - cm;
- cm1 = (c<<8) - cm;
- c1m1 = ((256 - m)<<8) - cm1;
- c1m1y = c1m1 * y;
- c1m1y1 = (c1m1<<7) - c1m1y;
- c1my = c1m * y;
- c1my1 = (c1m<<7) - c1my;
- cm1y = cm1 * y;
- cm1y1 = (cm1<<7) - cm1y;
- cmy = cm * y;
- cmy1 = (cm<<7) - cmy;
-
- /* this is a matrix multiplication, unrolled for performance */
- x1 = c1m1y1 * k; /* 0 0 0 1 */
- x0 = (c1m1y1<<8) - x1; /* 0 0 0 0 */
- x1 = x1>>8; /* From 23 fractional bits to 15 */
- r = g = b = x0;
- r += 35 * x1; /* 0.1373 */
- g += 31 * x1; /* 0.1216 */
- b += 32 * x1; /* 0.1255 */
-
- x1 = c1m1y * k; /* 0 0 1 1 */
- x0 = (c1m1y<<8) - x1; /* 0 0 1 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- r += 28 * x1; /* 0.1098 */
- g += 26 * x1; /* 0.1020 */
- r += x0;
- x0 >>= 8; /* From 23 fractional bits to 15 */
- g += 243 * x0; /* 0.9490 */
-
- x1 = c1my1 * k; /* 0 1 0 1 */
- x0 = (c1my1<<8) - x1; /* 0 1 0 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- r += 36 * x1; /* 0.1412 */
- r += 237 * x0; /* 0.9255 */
- b += 141 * x0; /* 0.5490 */
-
- x1 = c1my * k; /* 0 1 1 1 */
- x0 = (c1my<<8) - x1; /* 0 1 1 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- r += 34 * x1; /* 0.1333 */
- r += 238 * x0; /* 0.9294 */
- g += 28 * x0; /* 0.1098 */
- b += 36 * x0; /* 0.1412 */
-
- x1 = cm1y1 * k; /* 1 0 0 1 */
- x0 = (cm1y1<<8) - x1; /* 1 0 0 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- g += 15 * x1; /* 0.0588 */
- b += 36 * x1; /* 0.1412 */
- g += 174 * x0; /* 0.6784 */
- b += 240 * x0; /* 0.9373 */
-
- x1 = cm1y * k; /* 1 0 1 1 */
- x0 = (cm1y<<8) - x1; /* 1 0 1 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- g += 19 * x1; /* 0.0745 */
- g += 167 * x0; /* 0.6510 */
- b += 80 * x0; /* 0.3137 */
-
- x1 = cmy1 * k; /* 1 1 0 1 */
- x0 = (cmy1<<8) - x1; /* 1 1 0 0 */
- x1 >>= 8; /* From 23 fractional bits to 15 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- b += 2 * x1; /* 0.0078 */
- r += 46 * x0; /* 0.1804 */
- g += 49 * x0; /* 0.1922 */
- b += 147 * x0; /* 0.5725 */
-
- x0 = cmy * (256-k); /* 1 1 1 0 */
- x0 >>= 8; /* From 23 fractional bits to 15 */
- r += 54 * x0; /* 0.2118 */
- g += 54 * x0; /* 0.2119 */
- b += 57 * x0; /* 0.2235 */
-
- r -= (r>>8);
- g -= (g>>8);
- b -= (b>>8);
- r = r>>23;
- g = g>>23;
- b = b>>23;
- C = c;
- M = m;
- Y = y;
- K = k;
- }
- d[0] = r;
- d[1] = g;
- d[2] = b;
-#else
- d[0] = 255 - (unsigned char)fz_mini(s[0] + s[3], 255);
- d[1] = 255 - (unsigned char)fz_mini(s[1] + s[3], 255);
- d[2] = 255 - (unsigned char)fz_mini(s[2] + s[3], 255);
-#endif
- d[3] = s[4];
- s += 5;
- d += 4;
- }
-#endif
-}
-
-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;
- int n = src->w * src->h;
- while (n--)
- {
-#ifdef SLOWCMYK
- float cmyk[4], rgb[3];
- cmyk[0] = s[0] / 255.0f;
- cmyk[1] = s[1] / 255.0f;
- cmyk[2] = s[2] / 255.0f;
- cmyk[3] = s[3] / 255.0f;
- cmyk_to_rgb(ctx, NULL, cmyk, rgb);
- d[0] = rgb[2] * 255;
- d[1] = rgb[1] * 255;
- d[2] = rgb[0] * 255;
-#else
- d[0] = 255 - (unsigned char)fz_mini(s[2] + s[3], 255);
- d[1] = 255 - (unsigned char)fz_mini(s[1] + s[3], 255);
- d[2] = 255 - (unsigned char)fz_mini(s[0] + s[3], 255);
-#endif
- d[3] = s[4];
- s += 5;
- d += 4;
- }
-}
-
-static void fast_rgb_to_bgr(fz_pixmap *dst, fz_pixmap *src)
-{
- unsigned char *s = src->samples;
- unsigned char *d = dst->samples;
- int n = src->w * src->h;
- while (n--)
- {
- d[0] = s[2];
- d[1] = s[1];
- d[2] = s[0];
- d[3] = s[3];
- s += 4;
- d += 4;
- }
-}
-
-static void
-fz_std_conv_pixmap(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src)
-{
- float srcv[FZ_MAX_COLORS];
- float dstv[FZ_MAX_COLORS];
- int srcn, dstn;
- int k, i;
- unsigned int xy;
-
- fz_colorspace *ss = src->colorspace;
- fz_colorspace *ds = dst->colorspace;
-
- unsigned char *s = src->samples;
- unsigned char *d = dst->samples;
-
- assert(src->w == dst->w && src->h == dst->h);
- assert(src->n == ss->n + 1);
- assert(dst->n == ds->n + 1);
-
- srcn = ss->n;
- dstn = ds->n;
-
- xy = (unsigned int)(src->w * src->h);
-
- /* Special case for Lab colorspace (scaling of components to float) */
- if (!strcmp(ss->name, "Lab") && srcn == 3)
- {
- fz_color_converter cc;
-
- fz_lookup_color_converter(&cc, ctx, ds, ss);
- for (; xy > 0; xy--)
- {
- srcv[0] = *s++ / 255.0f * 100;
- srcv[1] = *s++ - 128;
- srcv[2] = *s++ - 128;
-
- cc.convert(&cc, dstv, srcv);
-
- for (k = 0; k < dstn; k++)
- *d++ = dstv[k] * 255;
-
- *d++ = *s++;
- }
- }
-
- /* Brute-force for small images */
- else if (xy < 256)
- {
- fz_color_converter cc;
-
- fz_lookup_color_converter(&cc, ctx, ds, ss);
- for (; xy > 0; xy--)
- {
- for (k = 0; k < srcn; k++)
- srcv[k] = *s++ / 255.0f;
-
- cc.convert(&cc, dstv, srcv);
-
- for (k = 0; k < dstn; k++)
- *d++ = dstv[k] * 255;
-
- *d++ = *s++;
- }
- }
-
- /* 1-d lookup table for separation and similar colorspaces */
- else if (srcn == 1)
- {
- unsigned char lookup[FZ_MAX_COLORS * 256];
- fz_color_converter cc;
-
- fz_lookup_color_converter(&cc, ctx, ds, ss);
- for (i = 0; i < 256; i++)
- {
- srcv[0] = i / 255.0f;
- cc.convert(&cc, dstv, srcv);
- for (k = 0; k < dstn; k++)
- lookup[i * dstn + k] = dstv[k] * 255;
- }
-
- for (; xy > 0; xy--)
- {
- i = *s++;
- for (k = 0; k < dstn; k++)
- *d++ = lookup[i * dstn + k];
- *d++ = *s++;
- }
- }
-
- /* Memoize colors using a hash table for the general case */
- else
- {
- fz_hash_table *lookup;
- unsigned char *color;
- unsigned char dummy = s[0] ^ 255;
- unsigned char *sold = &dummy;
- fz_color_converter cc;
-
- fz_lookup_color_converter(&cc, ctx, ds, ss);
- lookup = fz_new_hash_table(ctx, 509, srcn, -1);
-
- for (; xy > 0; xy--)
- {
- if (*s == *sold && memcmp(sold,s,srcn) == 0)
- {
- sold = s;
- memcpy(d, d-dstn-1, dstn);
- d += dstn;
- s += srcn;
- *d++ = *s++;
- }
- else
- {
- sold = s;
- color = fz_hash_find(ctx, lookup, s);
- if (color)
- {
- memcpy(d, color, dstn);
- s += srcn;
- d += dstn;
- *d++ = *s++;
- }
- else
- {
- for (k = 0; k < srcn; k++)
- srcv[k] = *s++ / 255.0f;
- cc.convert(&cc, dstv, srcv);
- for (k = 0; k < dstn; k++)
- *d++ = dstv[k] * 255;
-
- fz_hash_insert(ctx, lookup, s - srcn, d - dstn);
-
- *d++ = *s++;
- }
- }
- }
-
- fz_free_hash(ctx, lookup);
- }
-}
-
-void
-fz_convert_pixmap(fz_context *ctx, fz_pixmap *dp, fz_pixmap *sp)
-{
- fz_colorspace *ss = sp->colorspace;
- fz_colorspace *ds = dp->colorspace;
-
- assert(ss && ds);
-
- dp->interpolate = sp->interpolate;
-
- if (ss == fz_default_gray)
- {
- if (ds == fz_default_rgb) fast_gray_to_rgb(dp, sp);
- else if (ds == fz_default_bgr) fast_gray_to_rgb(dp, sp); /* bgr == rgb here */
- else if (ds == fz_default_cmyk) fast_gray_to_cmyk(dp, sp);
- else fz_std_conv_pixmap(ctx, dp, sp);
- }
-
- else if (ss == fz_default_rgb)
- {
- if (ds == fz_default_gray) fast_rgb_to_gray(dp, sp);
- else if (ds == fz_default_bgr) fast_rgb_to_bgr(dp, sp);
- else if (ds == fz_default_cmyk) fast_rgb_to_cmyk(dp, sp);
- else fz_std_conv_pixmap(ctx, dp, sp);
- }
-
- else if (ss == fz_default_bgr)
- {
- if (ds == fz_default_gray) fast_bgr_to_gray(dp, sp);
- else if (ds == fz_default_rgb) fast_rgb_to_bgr(dp, sp); /* bgr = rgb here */
- else if (ds == fz_default_cmyk) fast_bgr_to_cmyk(sp, dp);
- else fz_std_conv_pixmap(ctx, dp, sp);
- }
-
- else if (ss == fz_default_cmyk)
- {
- if (ds == fz_default_gray) fast_cmyk_to_gray(dp, sp);
- else if (ds == fz_default_bgr) fast_cmyk_to_bgr(ctx, dp, sp);
- else if (ds == fz_default_rgb) fast_cmyk_to_rgb(ctx, dp, sp);
- else fz_std_conv_pixmap(ctx, dp, sp);
- }
-
- else fz_std_conv_pixmap(ctx, dp, sp);
-}
-
-/* Convert a single color */
-
-static void
-std_conv_color(fz_color_converter *cc, float *dstv, float *srcv)
-{
- float rgb[3];
- int i;
- fz_colorspace *srcs = cc->ss;
- fz_colorspace *dsts = cc->ds;
- fz_context *ctx = cc->ctx;
-
- if (srcs != dsts)
- {
- assert(srcs->to_rgb && dsts->from_rgb);
- srcs->to_rgb(ctx, srcs, srcv, rgb);
- dsts->from_rgb(ctx, dsts, rgb, dstv);
- for (i = 0; i < dsts->n; i++)
- dstv[i] = fz_clamp(dstv[i], 0, 1);
- }
- else
- {
- for (i = 0; i < srcs->n; i++)
- dstv[i] = srcv[i];
- }
-}
-
-static void
-g2rgb(fz_color_converter *cc, float *dv, float *sv)
-{
- dv[0] = sv[0];
- dv[1] = sv[0];
- dv[2] = sv[0];
-}
-
-static void
-g2cmyk(fz_color_converter *cc, float *dv, float *sv)
-{
- dv[0] = 0;
- dv[1] = 0;
- dv[2] = 0;
- dv[3] = sv[0];
-}
-
-static void
-rgb2g(fz_color_converter *cc, float *dv, float *sv)
-{
- dv[0] = sv[0] * 0.3f + sv[1] * 0.59f + sv[2] * 0.11f;
-}
-
-static void
-rgb2bgr(fz_color_converter *cc, float *dv, float *sv)
-{
- dv[0] = sv[2];
- dv[1] = sv[1];
- dv[2] = sv[0];
-}
-
-static void
-rgb2cmyk(fz_color_converter *cc, float *dv, float *sv)
-{
- float c = 1 - sv[0];
- float m = 1 - sv[1];
- float y = 1 - sv[2];
- float k = fz_min(c, fz_min(m, y));
- dv[0] = c - k;
- dv[1] = m - k;
- dv[2] = y - k;
- dv[3] = k;
-}
-
-static void
-bgr2g(fz_color_converter *cc, float *dv, float *sv)
-{
- dv[0] = sv[0] * 0.11f + sv[1] * 0.59f + sv[2] * 0.3f;
-}
-
-static void
-bgr2cmyk(fz_color_converter *cc, float *dv, float *sv)
-{
- float c = 1 - sv[2];
- float m = 1 - sv[1];
- float y = 1 - sv[0];
- float k = fz_min(c, fz_min(m, y));
- dv[0] = c - k;
- dv[1] = m - k;
- dv[2] = y - k;
- dv[3] = k;
-}
-
-static void
-cmyk2g(fz_color_converter *cc, float *dv, float *sv)
-{
- float c = sv[0] * 0.3f;
- float m = sv[1] * 0.59f;
- float y = sv[2] * 0.11f;
- dv[0] = 1 - fz_min(c + m + y + sv[3], 1);
-}
-
-static void
-cmyk2rgb(fz_color_converter *cc, float *dv, float *sv)
-{
-#ifdef SLOWCMYK
- cmyk_to_rgb(cc->ctx, NULL, sv, dv);
-#else
- dv[0] = 1 - fz_min(sv[0] + sv[3], 1);
- dv[1] = 1 - fz_min(sv[1] + sv[3], 1);
- dv[2] = 1 - fz_min(sv[2] + sv[3], 1);
-#endif
-}
-
-static void
-cmyk2bgr(fz_color_converter *cc, float *dv, float *sv)
-{
-#ifdef SLOWCMYK
- float rgb[3];
- cmyk_to_rgb(cc->ctx, NULL, sv, rgb);
- dv[0] = rgb[2];
- dv[1] = rgb[1];
- dv[2] = rgb[0];
-#else
- dv[0] = 1 - fz_min(sv[2] + sv[3], 1);
- dv[1] = 1 - fz_min(sv[1] + sv[3], 1);
- dv[2] = 1 - fz_min(sv[0] + sv[3], 1);
-#endif
-}
-
-void fz_lookup_color_converter(fz_color_converter *cc, fz_context *ctx, fz_colorspace *ds, fz_colorspace *ss)
-{
- cc->ctx = ctx;
- cc->ds = ds;
- cc->ss = ss;
- if (ss == fz_default_gray)
- {
- if ((ds == fz_default_rgb) || (ds == fz_default_bgr))
- cc->convert = g2rgb;
- else if (ds == fz_default_cmyk)
- cc->convert = g2cmyk;
- else
- cc->convert = std_conv_color;
- }
-
- else if (ss == fz_default_rgb)
- {
- if (ds == fz_default_gray)
- cc->convert = rgb2g;
- else if (ds == fz_default_bgr)
- cc->convert = rgb2bgr;
- else if (ds == fz_default_cmyk)
- cc->convert = rgb2cmyk;
- else
- cc->convert = std_conv_color;
- }
-
- else if (ss == fz_default_bgr)
- {
- if (ds == fz_default_gray)
- cc->convert = bgr2g;
- else if (ds == fz_default_rgb)
- cc->convert = rgb2bgr;
- else if (ds == fz_default_cmyk)
- cc->convert = bgr2cmyk;
- else
- cc->convert = std_conv_color;
- }
-
- else if (ss == fz_default_cmyk)
- {
- if (ds == fz_default_gray)
- cc->convert = cmyk2g;
- else if (ds == fz_default_rgb)
- cc->convert = cmyk2rgb;
- else if (ds == fz_default_bgr)
- cc->convert = cmyk2bgr;
- else
- cc->convert = std_conv_color;
- }
-
- else
- cc->convert = std_conv_color;
-}
-
-void
-fz_convert_color(fz_context *ctx, fz_colorspace *ds, float *dv, fz_colorspace *ss, float *sv)
-{
- fz_color_converter cc;
-
- fz_lookup_color_converter(&cc, ctx, ds, ss);
- cc.convert(&cc, dv, sv);
-}
-
-/* Indexed */
-
-struct indexed
-{
- fz_colorspace *base;
- int high;
- unsigned char *lookup;
-};
-
-static void
-indexed_to_rgb(fz_context *ctx, fz_colorspace *cs, float *color, float *rgb)
-{
- struct indexed *idx = cs->data;
- float alt[FZ_MAX_COLORS];
- int i, k;
- i = color[0] * 255;
- i = fz_clampi(i, 0, idx->high);
- for (k = 0; k < idx->base->n; k++)
- alt[k] = idx->lookup[i * idx->base->n + k] / 255.0f;
- idx->base->to_rgb(ctx, idx->base, alt, rgb);
-}
-
-static void
-free_indexed(fz_context *ctx, fz_colorspace *cs)
-{
- struct indexed *idx = cs->data;
- if (idx->base)
- fz_drop_colorspace(ctx, idx->base);
- fz_free(ctx, idx->lookup);
- fz_free(ctx, idx);
-}
-
-fz_colorspace *
-fz_new_indexed_colorspace(fz_context *ctx, fz_colorspace *base, int high, unsigned char *lookup)
-{
- fz_colorspace *cs;
- struct indexed *idx;
-
- idx = fz_malloc_struct(ctx, struct indexed);
- idx->lookup = lookup;
- idx->base = base;
- idx->high = high;
-
- fz_try(ctx)
- {
- cs = fz_new_colorspace(ctx, "Indexed", 1);
- cs->to_rgb = indexed_to_rgb;
- cs->free_data = free_indexed;
- cs->data = idx;
- cs->size += sizeof(*idx) + (base->n * (idx->high + 1)) + base->size;
- }
- fz_catch(ctx)
- {
- fz_free(ctx, idx);
- fz_rethrow_message(ctx, "failed to create indexed colorspace");
- }
- return cs;
-}
-
-fz_pixmap *
-fz_expand_indexed_pixmap(fz_context *ctx, fz_pixmap *src)
-{
- struct indexed *idx;
- fz_pixmap *dst;
- unsigned char *s, *d;
- int y, x, k, n, high;
- unsigned char *lookup;
- fz_irect bbox;
-
- assert(src->colorspace->to_rgb == indexed_to_rgb);
- assert(src->n == 2);
-
- idx = src->colorspace->data;
- high = idx->high;
- lookup = idx->lookup;
- n = idx->base->n;
-
- dst = fz_new_pixmap_with_bbox(ctx, idx->base, fz_pixmap_bbox(ctx, src, &bbox));
- s = src->samples;
- d = dst->samples;
-
- for (y = 0; y < src->h; y++)
- {
- for (x = 0; x < src->w; x++)
- {
- int v = *s++;
- int a = *s++;
- v = fz_mini(v, high);
- for (k = 0; k < n; k++)
- *d++ = fz_mul255(lookup[v * n + k], a);
- *d++ = a;
- }
- }
-
- dst->interpolate = src->interpolate;
-
- return dst;
-}
diff --git a/fitz/res_font.c b/fitz/res_font.c
deleted file mode 100644
index e8613f84..00000000
--- a/fitz/res_font.c
+++ /dev/null
@@ -1,1094 +0,0 @@
-#include "mupdf/fitz.h"
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_STROKER_H
-
-#define MAX_BBOX_TABLE_SIZE 4096
-
-/* 20 degrees */
-#define SHEAR 0.36397f
-
-static void fz_drop_freetype(fz_context *ctx);
-
-static fz_font *
-fz_new_font(fz_context *ctx, char *name, int use_glyph_bbox, int glyph_count)
-{
- fz_font *font;
- int i;
-
- font = fz_malloc_struct(ctx, fz_font);
- font->refs = 1;
-
- if (name)
- fz_strlcpy(font->name, name, sizeof font->name);
- else
- fz_strlcpy(font->name, "(null)", sizeof font->name);
-
- font->ft_face = NULL;
- font->ft_substitute = 0;
- font->ft_bold = 0;
- font->ft_italic = 0;
- font->ft_hint = 0;
-
- font->ft_file = NULL;
- font->ft_data = NULL;
- font->ft_size = 0;
-
- font->t3matrix = fz_identity;
- font->t3resources = NULL;
- font->t3procs = NULL;
- font->t3lists = NULL;
- font->t3widths = NULL;
- font->t3flags = NULL;
- font->t3doc = NULL;
- font->t3run = NULL;
-
- font->bbox.x0 = 0;
- font->bbox.y0 = 0;
- font->bbox.x1 = 1;
- font->bbox.y1 = 1;
-
- font->use_glyph_bbox = use_glyph_bbox;
- if (use_glyph_bbox && glyph_count <= MAX_BBOX_TABLE_SIZE)
- {
- font->bbox_count = glyph_count;
- font->bbox_table = fz_malloc_array(ctx, glyph_count, sizeof(fz_rect));
- for (i = 0; i < glyph_count; i++)
- font->bbox_table[i] = fz_infinite_rect;
- }
- else
- {
- if (use_glyph_bbox)
- fz_warn(ctx, "not building glyph bbox table for font '%s' with %d glyphs", font->name, glyph_count);
- font->bbox_count = 0;
- font->bbox_table = NULL;
- }
-
- font->width_count = 0;
- font->width_table = NULL;
-
- return font;
-}
-
-fz_font *
-fz_keep_font(fz_context *ctx, fz_font *font)
-{
- if (!font)
- return NULL;
- fz_lock(ctx, FZ_LOCK_ALLOC);
- font->refs ++;
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- return font;
-}
-
-void
-fz_drop_font(fz_context *ctx, fz_font *font)
-{
- int fterr;
- int i, drop;
-
- fz_lock(ctx, FZ_LOCK_ALLOC);
- drop = (font && --font->refs == 0);
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- if (!drop)
- return;
-
- if (font->t3procs)
- {
- if (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]);
- if (font->t3lists[i])
- fz_drop_display_list(ctx, font->t3lists[i]);
- }
- fz_free(ctx, font->t3procs);
- fz_free(ctx, font->t3lists);
- fz_free(ctx, font->t3widths);
- fz_free(ctx, font->t3flags);
- }
-
- if (font->ft_face)
- {
- fz_lock(ctx, FZ_LOCK_FREETYPE);
- fterr = FT_Done_Face((FT_Face)font->ft_face);
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
- if (fterr)
- fz_warn(ctx, "freetype finalizing face: %s", ft_error_string(fterr));
- fz_drop_freetype(ctx);
- }
-
- fz_free(ctx, font->ft_file);
- fz_free(ctx, font->ft_data);
- fz_free(ctx, font->bbox_table);
- fz_free(ctx, font->width_table);
- fz_free(ctx, font);
-}
-
-void
-fz_set_font_bbox(fz_context *ctx, fz_font *font, float xmin, float ymin, float xmax, float ymax)
-{
- if (xmin >= xmax || ymin >= ymax)
- {
- /* Invalid bbox supplied. It would be prohibitively slow to
- * measure the true one, so make one up. */
- font->bbox.x0 = -1;
- font->bbox.y0 = -1;
- font->bbox.x1 = 2;
- font->bbox.y1 = 2;
- }
- else
- {
- font->bbox.x0 = xmin;
- font->bbox.y0 = ymin;
- font->bbox.x1 = xmax;
- font->bbox.y1 = ymax;
- }
-}
-
-/*
- * Freetype hooks
- */
-
-struct fz_font_context_s {
- int ctx_refs;
- FT_Library ftlib;
- int ftlib_refs;
-};
-
-#undef __FTERRORS_H__
-#define FT_ERRORDEF(e, v, s) { (e), (s) },
-#define FT_ERROR_START_LIST
-#define FT_ERROR_END_LIST { 0, NULL }
-
-struct ft_error
-{
- int err;
- char *str;
-};
-
-void fz_new_font_context(fz_context *ctx)
-{
- ctx->font = fz_malloc_struct(ctx, fz_font_context);
- ctx->font->ctx_refs = 1;
- ctx->font->ftlib = NULL;
- ctx->font->ftlib_refs = 0;
-}
-
-fz_font_context *
-fz_keep_font_context(fz_context *ctx)
-{
- if (!ctx || !ctx->font)
- return NULL;
- fz_lock(ctx, FZ_LOCK_ALLOC);
- ctx->font->ctx_refs++;
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- return ctx->font;
-}
-
-void fz_drop_font_context(fz_context *ctx)
-{
- int drop;
- if (!ctx || !ctx->font)
- return;
- fz_lock(ctx, FZ_LOCK_ALLOC);
- drop = --ctx->font->ctx_refs;
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- if (drop == 0)
- fz_free(ctx, ctx->font);
-}
-
-static const struct ft_error ft_errors[] =
-{
-#include FT_ERRORS_H
-};
-
-char *ft_error_string(int err)
-{
- const struct ft_error *e;
-
- for (e = ft_errors; e->str; e++)
- if (e->err == err)
- return e->str;
-
- return "Unknown error";
-}
-
-static void
-fz_keep_freetype(fz_context *ctx)
-{
- int fterr;
- int maj, min, pat;
- fz_font_context *fct = ctx->font;
-
- fz_lock(ctx, FZ_LOCK_FREETYPE);
- if (fct->ftlib)
- {
- fct->ftlib_refs++;
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
- return;
- }
-
- fterr = FT_Init_FreeType(&fct->ftlib);
- if (fterr)
- {
- char *mess = ft_error_string(fterr);
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
- fz_throw(ctx, FZ_ERROR_GENERIC, "cannot init freetype: %s", mess);
- }
-
- FT_Library_Version(fct->ftlib, &maj, &min, &pat);
- if (maj == 2 && min == 1 && pat < 7)
- {
- fterr = FT_Done_FreeType(fct->ftlib);
- if (fterr)
- fz_warn(ctx, "freetype finalizing: %s", ft_error_string(fterr));
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
- fz_throw(ctx, FZ_ERROR_GENERIC, "freetype version too old: %d.%d.%d", maj, min, pat);
- }
-
- fct->ftlib_refs++;
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
-}
-
-static void
-fz_drop_freetype(fz_context *ctx)
-{
- int fterr;
- fz_font_context *fct = ctx->font;
-
- fz_lock(ctx, FZ_LOCK_FREETYPE);
- if (--fct->ftlib_refs == 0)
- {
- fterr = FT_Done_FreeType(fct->ftlib);
- if (fterr)
- fz_warn(ctx, "freetype finalizing: %s", ft_error_string(fterr));
- fct->ftlib = NULL;
- }
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
-}
-
-fz_font *
-fz_new_font_from_file(fz_context *ctx, char *name, char *path, int index, int use_glyph_bbox)
-{
- FT_Face face;
- fz_font *font;
- int fterr;
-
- fz_keep_freetype(ctx);
-
- fz_lock(ctx, FZ_LOCK_FREETYPE);
- fterr = FT_New_Face(ctx->font->ftlib, path, index, &face);
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
- if (fterr)
- {
- fz_drop_freetype(ctx);
- fz_throw(ctx, FZ_ERROR_GENERIC, "freetype: cannot load font: %s", ft_error_string(fterr));
- }
-
- if (!name)
- name = face->family_name;
-
- font = fz_new_font(ctx, name, use_glyph_bbox, face->num_glyphs);
- font->ft_face = face;
- fz_set_font_bbox(ctx, font,
- (float) face->bbox.xMin / face->units_per_EM,
- (float) face->bbox.yMin / face->units_per_EM,
- (float) face->bbox.xMax / face->units_per_EM,
- (float) face->bbox.yMax / face->units_per_EM);
-
- return font;
-}
-
-fz_font *
-fz_new_font_from_memory(fz_context *ctx, char *name, unsigned char *data, int len, int index, int use_glyph_bbox)
-{
- FT_Face face;
- fz_font *font;
- int fterr;
-
- fz_keep_freetype(ctx);
-
- fz_lock(ctx, FZ_LOCK_FREETYPE);
- fterr = FT_New_Memory_Face(ctx->font->ftlib, data, len, index, &face);
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
- if (fterr)
- {
- fz_drop_freetype(ctx);
- fz_throw(ctx, FZ_ERROR_GENERIC, "freetype: cannot load font: %s", ft_error_string(fterr));
- }
-
- if (!name)
- name = face->family_name;
-
- font = fz_new_font(ctx, name, use_glyph_bbox, face->num_glyphs);
- font->ft_face = face;
- fz_set_font_bbox(ctx, font,
- (float) face->bbox.xMin / face->units_per_EM,
- (float) face->bbox.yMin / face->units_per_EM,
- (float) face->bbox.xMax / face->units_per_EM,
- (float) face->bbox.yMax / face->units_per_EM);
-
- return font;
-}
-
-static fz_matrix *
-fz_adjust_ft_glyph_width(fz_context *ctx, fz_font *font, int gid, fz_matrix *trm)
-{
- /* Fudge the font matrix to stretch the glyph if we've substituted the font. */
- if (font->ft_substitute && font->width_table && gid < font->width_count)
- {
- FT_Error fterr;
- int subw;
- int realw;
- float scale;
-
- fz_lock(ctx, FZ_LOCK_FREETYPE);
- /* TODO: use FT_Get_Advance */
- fterr = FT_Set_Char_Size(font->ft_face, 1000, 1000, 72, 72);
- if (fterr)
- fz_warn(ctx, "freetype setting character size: %s", ft_error_string(fterr));
-
- fterr = FT_Load_Glyph(font->ft_face, gid,
- FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM);
- if (fterr)
- fz_warn(ctx, "freetype failed to load glyph: %s", ft_error_string(fterr));
-
- realw = ((FT_Face)font->ft_face)->glyph->metrics.horiAdvance;
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
- subw = font->width_table[gid];
- if (realw)
- scale = (float) subw / realw;
- else
- scale = 1;
-
- fz_pre_scale(trm, scale, 1);
- }
-
- return trm;
-}
-
-static fz_pixmap *
-fz_copy_ft_bitmap(fz_context *ctx, int left, int top, FT_Bitmap *bitmap)
-{
- fz_pixmap *pixmap;
- int y;
-
- pixmap = fz_new_pixmap(ctx, NULL, bitmap->width, bitmap->rows);
- pixmap->x = left;
- pixmap->y = top - bitmap->rows;
-
- if (bitmap->pixel_mode == FT_PIXEL_MODE_MONO)
- {
- for (y = 0; y < pixmap->h; y++)
- {
- unsigned char *out = pixmap->samples + (unsigned int)(y * pixmap->w);
- unsigned char *in = bitmap->buffer + (unsigned int)((pixmap->h - y - 1) * bitmap->pitch);
- unsigned char bit = 0x80;
- int w = pixmap->w;
- while (w--)
- {
- *out++ = (*in & bit) ? 255 : 0;
- bit >>= 1;
- if (bit == 0)
- {
- bit = 0x80;
- in++;
- }
- }
- }
- }
- else
- {
- for (y = 0; y < pixmap->h; y++)
- {
- memcpy(pixmap->samples + (unsigned int)(y * pixmap->w),
- bitmap->buffer + (unsigned int)((pixmap->h - y - 1) * bitmap->pitch),
- pixmap->w);
- }
- }
-
- return pixmap;
-}
-
-/* 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, const fz_matrix *trm, int aa)
-{
- FT_Face face = font->ft_face;
- FT_Matrix m;
- FT_Vector v;
- FT_Error fterr;
- fz_pixmap *result;
- fz_matrix local_trm = *trm;
-
- float strength = fz_matrix_expansion(trm) * 0.02f;
-
- fz_adjust_ft_glyph_width(ctx, font, gid, &local_trm);
-
- if (font->ft_italic)
- fz_pre_shear(&local_trm, SHEAR, 0);
-
- /*
- Freetype mutilates complex glyphs if they are loaded
- with FT_Set_Char_Size 1.0. it rounds the coordinates
- before applying transformation. to get more precision in
- freetype, we shift part of the scale in the matrix
- into FT_Set_Char_Size instead
- */
-
- m.xx = local_trm.a * 64; /* should be 65536 */
- m.yx = local_trm.b * 64;
- m.xy = local_trm.c * 64;
- m.yy = local_trm.d * 64;
- v.x = local_trm.e * 64;
- v.y = local_trm.f * 64;
-
- fz_lock(ctx, FZ_LOCK_FREETYPE);
- fterr = FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */
- if (fterr)
- fz_warn(ctx, "freetype setting character size: %s", ft_error_string(fterr));
- FT_Set_Transform(face, &m, &v);
-
- if (aa == 0)
- {
- /* enable grid fitting for non-antialiased rendering */
- float scale = fz_matrix_expansion(&local_trm);
- m.xx = local_trm.a * 65536 / scale;
- m.xy = local_trm.b * 65536 / scale;
- m.yx = local_trm.c * 65536 / scale;
- m.yy = local_trm.d * 65536 / scale;
- v.x = 0;
- v.y = 0;
-
- fterr = FT_Set_Char_Size(face, 64 * scale, 64 * scale, 72, 72);
- if (fterr)
- fz_warn(ctx, "freetype setting character size: %s", ft_error_string(fterr));
- FT_Set_Transform(face, &m, &v);
- fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_TARGET_MONO);
- if (fterr) {
- fz_warn(ctx, "freetype load hinted glyph (gid %d): %s", gid, ft_error_string(fterr));
- goto retry_unhinted;
- }
- }
- else if (font->ft_hint)
- {
- /*
- Enable hinting, but keep the huge char size so that
- it is hinted for a character. This will in effect nullify
- the effect of grid fitting. This form of hinting should
- only be used for DynaLab and similar tricky TrueType fonts,
- so that we get the correct outline shape.
- */
- fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP);
- if (fterr) {
- fz_warn(ctx, "freetype load hinted glyph (gid %d): %s", gid, ft_error_string(fterr));
- goto retry_unhinted;
- }
- }
- else
- {
-retry_unhinted:
- fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING);
- if (fterr)
- {
- fz_warn(ctx, "freetype load glyph (gid %d): %s", gid, ft_error_string(fterr));
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
- return NULL;
- }
- }
-
- if (font->ft_bold)
- {
- FT_Outline_Embolden(&face->glyph->outline, strength * 64);
- FT_Outline_Translate(&face->glyph->outline, -strength * 32, -strength * 32);
- }
-
- 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));
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
- return NULL;
- }
-
- fz_try(ctx)
- {
- result = fz_copy_ft_bitmap(ctx, face->glyph->bitmap_left, face->glyph->bitmap_top, &face->glyph->bitmap);
- }
- fz_always(ctx)
- {
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
-
- return result;
-}
-
-fz_pixmap *
-fz_render_ft_stroked_glyph(fz_context *ctx, fz_font *font, int gid, const fz_matrix *trm, const fz_matrix *ctm, fz_stroke_state *state)
-{
- FT_Face face = font->ft_face;
- float expansion = fz_matrix_expansion(ctm);
- int linewidth = state->linewidth * expansion * 64 / 2;
- FT_Matrix m;
- FT_Vector v;
- FT_Error fterr;
- FT_Stroker stroker;
- FT_Glyph glyph;
- FT_BitmapGlyph bitmap;
- fz_pixmap *pixmap;
- FT_Stroker_LineJoin line_join;
- fz_matrix local_trm = *trm;
-
- fz_adjust_ft_glyph_width(ctx, font, gid, &local_trm);
-
- if (font->ft_italic)
- fz_pre_shear(&local_trm, SHEAR, 0);
-
- m.xx = local_trm.a * 64; /* should be 65536 */
- m.yx = local_trm.b * 64;
- m.xy = local_trm.c * 64;
- m.yy = local_trm.d * 64;
- v.x = local_trm.e * 64;
- v.y = local_trm.f * 64;
-
- fz_lock(ctx, FZ_LOCK_FREETYPE);
- fterr = FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */
- if (fterr)
- {
- fz_warn(ctx, "FT_Set_Char_Size: %s", ft_error_string(fterr));
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
- return NULL;
- }
-
- FT_Set_Transform(face, &m, &v);
-
- fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING);
- if (fterr)
- {
- fz_warn(ctx, "FT_Load_Glyph(gid %d): %s", gid, ft_error_string(fterr));
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
- return NULL;
- }
-
- fterr = FT_Stroker_New(ctx->font->ftlib, &stroker);
- if (fterr)
- {
- fz_warn(ctx, "FT_Stroker_New: %s", ft_error_string(fterr));
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
- return NULL;
- }
-
-#if FREETYPE_MAJOR * 10000 + FREETYPE_MINOR * 100 + FREETYPE_PATCH > 20405
- /* New freetype */
- line_join =
- state->linejoin == FZ_LINEJOIN_MITER ? FT_STROKER_LINEJOIN_MITER_FIXED :
- state->linejoin == FZ_LINEJOIN_ROUND ? FT_STROKER_LINEJOIN_ROUND :
- state->linejoin == FZ_LINEJOIN_BEVEL ? FT_STROKER_LINEJOIN_BEVEL :
- FT_STROKER_LINEJOIN_MITER_VARIABLE;
-#else
- /* Old freetype */
- line_join =
- state->linejoin == FZ_LINEJOIN_MITER ? FT_STROKER_LINEJOIN_MITER :
- state->linejoin == FZ_LINEJOIN_ROUND ? FT_STROKER_LINEJOIN_ROUND :
- state->linejoin == FZ_LINEJOIN_BEVEL ? FT_STROKER_LINEJOIN_BEVEL :
- FT_STROKER_LINEJOIN_MITER;
-#endif
- FT_Stroker_Set(stroker, linewidth, (FT_Stroker_LineCap)state->start_cap, line_join, state->miterlimit * 65536);
-
- fterr = FT_Get_Glyph(face->glyph, &glyph);
- if (fterr)
- {
- fz_warn(ctx, "FT_Get_Glyph: %s", ft_error_string(fterr));
- FT_Stroker_Done(stroker);
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
- return NULL;
- }
-
- fterr = FT_Glyph_Stroke(&glyph, stroker, 1);
- if (fterr)
- {
- fz_warn(ctx, "FT_Glyph_Stroke: %s", ft_error_string(fterr));
- FT_Done_Glyph(glyph);
- FT_Stroker_Done(stroker);
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
- return NULL;
- }
-
- FT_Stroker_Done(stroker);
-
- 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));
- FT_Done_Glyph(glyph);
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
- return NULL;
- }
-
- bitmap = (FT_BitmapGlyph)glyph;
- fz_try(ctx)
- {
- pixmap = fz_copy_ft_bitmap(ctx, bitmap->left, bitmap->top, &bitmap->bitmap);
- }
- fz_always(ctx)
- {
- FT_Done_Glyph(glyph);
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
-
- return pixmap;
-}
-
-static fz_rect *
-fz_bound_ft_glyph(fz_context *ctx, fz_font *font, int gid, const fz_matrix *trm, fz_rect *bounds)
-{
- FT_Face face = font->ft_face;
- FT_Error fterr;
- FT_BBox cbox;
- FT_Matrix m;
- FT_Vector v;
-
- // TODO: refactor loading into fz_load_ft_glyph
- // TODO: cache results
-
- float strength = fz_matrix_expansion(trm) * 0.02f;
- fz_matrix local_trm = *trm;
-
- fz_adjust_ft_glyph_width(ctx, font, gid, &local_trm);
-
- if (font->ft_italic)
- fz_pre_shear(&local_trm, SHEAR, 0);
-
- m.xx = local_trm.a * 64; /* should be 65536 */
- m.yx = local_trm.b * 64;
- m.xy = local_trm.c * 64;
- m.yy = local_trm.d * 64;
- v.x = local_trm.e * 64;
- v.y = local_trm.f * 64;
-
- fz_lock(ctx, FZ_LOCK_FREETYPE);
- fterr = FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */
- if (fterr)
- fz_warn(ctx, "freetype setting character size: %s", ft_error_string(fterr));
- FT_Set_Transform(face, &m, &v);
-
- fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING);
- if (fterr)
- {
- fz_warn(ctx, "freetype load glyph (gid %d): %s", gid, ft_error_string(fterr));
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
- bounds->x0 = bounds->x1 = local_trm.e;
- bounds->y0 = bounds->y1 = local_trm.f;
- return bounds;
- }
-
- if (font->ft_bold)
- {
- FT_Outline_Embolden(&face->glyph->outline, strength * 64);
- FT_Outline_Translate(&face->glyph->outline, -strength * 32, -strength * 32);
- }
-
- FT_Outline_Get_CBox(&face->glyph->outline, &cbox);
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
- bounds->x0 = cbox.xMin / 64.0f;
- bounds->y0 = cbox.yMin / 64.0f;
- bounds->x1 = cbox.xMax / 64.0f;
- bounds->y1 = cbox.yMax / 64.0f;
-
- if (fz_is_empty_rect(bounds))
- {
- bounds->x0 = bounds->x1 = local_trm.e;
- bounds->y0 = bounds->y1 = local_trm.f;
- }
-
- return bounds;
-}
-
-/* Turn FT_Outline into a fz_path */
-
-struct closure {
- fz_context *ctx;
- fz_path *path;
- float x, y;
-};
-
-static int move_to(const FT_Vector *p, void *cc)
-{
- fz_context *ctx = ((struct closure *)cc)->ctx;
- fz_path *path = ((struct closure *)cc)->path;
- float tx = ((struct closure *)cc)->x;
- float ty = ((struct closure *)cc)->y;
- fz_moveto(ctx, path, tx + p->x / 64.0f, ty + p->y / 64.0f);
- return 0;
-}
-
-static int line_to(const FT_Vector *p, void *cc)
-{
- fz_context *ctx = ((struct closure *)cc)->ctx;
- fz_path *path = ((struct closure *)cc)->path;
- float tx = ((struct closure *)cc)->x;
- float ty = ((struct closure *)cc)->y;
- fz_lineto(ctx, path, tx + p->x / 64.0f, ty + p->y / 64.0f);
- return 0;
-}
-
-static int conic_to(const FT_Vector *c, const FT_Vector *p, void *cc)
-{
- fz_context *ctx = ((struct closure *)cc)->ctx;
- fz_path *path = ((struct closure *)cc)->path;
- float tx = ((struct closure *)cc)->x;
- float ty = ((struct closure *)cc)->y;
- fz_point s, c1, c2;
- float cx = tx + c->x / 64.0f, cy = ty + c->y / 64.0f;
- float px = tx + p->x / 64.0f, py = ty + p->y / 64.0f;
- s = fz_currentpoint(ctx, path);
- c1.x = (s.x + cx * 2) / 3;
- c1.y = (s.y + cy * 2) / 3;
- c2.x = (px + cx * 2) / 3;
- c2.y = (py + cy * 2) / 3;
- fz_curveto(ctx, path, c1.x, c1.y, c2.x, c2.y, px, py);
- return 0;
-}
-
-static int cubic_to(const FT_Vector *c1, const FT_Vector *c2, const FT_Vector *p, void *cc)
-{
- fz_context *ctx = ((struct closure *)cc)->ctx;
- fz_path *path = ((struct closure *)cc)->path;
- float tx = ((struct closure *)cc)->x;
- float ty = ((struct closure *)cc)->y;
- fz_curveto(ctx, path,
- tx + c1->x/64.0f, ty + c1->y/64.0f,
- tx + c2->x/64.0f, ty + c2->y/64.0f,
- tx + p->x/64.0f, ty + p->y/64.0f);
- return 0;
-}
-
-static const FT_Outline_Funcs outline_funcs = {
- move_to, line_to, conic_to, cubic_to, 0, 0
-};
-
-fz_path *
-fz_outline_ft_glyph(fz_context *ctx, fz_font *font, int gid, const fz_matrix *trm)
-{
- struct closure cc;
- FT_Face face = font->ft_face;
- FT_Matrix m;
- FT_Vector v;
- int fterr;
- fz_matrix local_trm = *trm;
-
- float strength = fz_matrix_expansion(trm) * 0.02f;
-
- fz_adjust_ft_glyph_width(ctx, font, gid, &local_trm);
-
- if (font->ft_italic)
- fz_pre_shear(&local_trm, SHEAR, 0);
-
- m.xx = local_trm.a * 64; /* should be 65536 */
- m.yx = local_trm.b * 64;
- m.xy = local_trm.c * 64;
- m.yy = local_trm.d * 64;
- v.x = 0;
- v.y = 0;
-
- fz_lock(ctx, FZ_LOCK_FREETYPE);
-
- fterr = FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */
- if (fterr)
- fz_warn(ctx, "freetype setting character size: %s", ft_error_string(fterr));
- FT_Set_Transform(face, &m, &v);
-
- fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING);
- if (fterr)
- {
- fz_warn(ctx, "freetype load glyph (gid %d): %s", gid, ft_error_string(fterr));
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
- return NULL;
- }
-
- if (font->ft_bold)
- {
- FT_Outline_Embolden(&face->glyph->outline, strength * 64);
- FT_Outline_Translate(&face->glyph->outline, -strength * 32, -strength * 32);
- }
-
- fz_try(ctx)
- {
- cc.ctx = ctx;
- cc.path = fz_new_path(ctx);
- cc.x = local_trm.e;
- cc.y = local_trm.f;
- fz_moveto(ctx, cc.path, cc.x, cc.y);
- FT_Outline_Decompose(&face->glyph->outline, &outline_funcs, &cc);
- fz_closepath(ctx, cc.path);
- }
- fz_always(ctx)
- {
- fz_unlock(ctx, FZ_LOCK_FREETYPE);
- }
- fz_catch(ctx)
- {
- fz_warn(ctx, "freetype cannot decompose outline");
- fz_free(ctx, cc.path);
- return NULL;
- }
-
- return cc.path;
-}
-
-/*
- * Type 3 fonts...
- */
-
-fz_font *
-fz_new_type3_font(fz_context *ctx, char *name, const fz_matrix *matrix)
-{
- fz_font *font;
- int i;
-
- font = fz_new_font(ctx, name, 1, 256);
- font->t3procs = fz_malloc_array(ctx, 256, sizeof(fz_buffer*));
- font->t3lists = fz_malloc_array(ctx, 256, sizeof(fz_display_list*));
- font->t3widths = fz_malloc_array(ctx, 256, sizeof(float));
- font->t3flags = fz_malloc_array(ctx, 256, sizeof(char));
-
- font->t3matrix = *matrix;
- for (i = 0; i < 256; i++)
- {
- font->t3procs[i] = NULL;
- font->t3lists[i] = NULL;
- font->t3widths[i] = 0;
- font->t3flags[i] = 0;
- }
-
- return font;
-}
-
-void
-fz_prepare_t3_glyph(fz_context *ctx, fz_font *font, int gid, int nested_depth)
-{
- fz_buffer *contents;
- fz_device *dev;
-
- contents = font->t3procs[gid];
- if (!contents)
- return;
-
- /* We've not already loaded this one! */
- assert(font->t3lists[gid] == NULL);
-
- font->t3lists[gid] = fz_new_display_list(ctx);
-
- dev = fz_new_list_device(ctx, font->t3lists[gid]);
- dev->flags = FZ_DEVFLAG_FILLCOLOR_UNDEFINED |
- FZ_DEVFLAG_STROKECOLOR_UNDEFINED |
- FZ_DEVFLAG_STARTCAP_UNDEFINED |
- FZ_DEVFLAG_DASHCAP_UNDEFINED |
- FZ_DEVFLAG_ENDCAP_UNDEFINED |
- FZ_DEVFLAG_LINEJOIN_UNDEFINED |
- FZ_DEVFLAG_MITERLIMIT_UNDEFINED |
- FZ_DEVFLAG_LINEWIDTH_UNDEFINED;
- font->t3run(font->t3doc, font->t3resources, contents, dev, &fz_identity, NULL, 0);
- font->t3flags[gid] = dev->flags;
- fz_free_device(dev);
-}
-
-static fz_rect *
-fz_bound_t3_glyph(fz_context *ctx, fz_font *font, int gid, const fz_matrix *trm, fz_rect *bounds)
-{
- fz_display_list *list;
- fz_matrix ctm;
- fz_device *dev;
-
- list = font->t3lists[gid];
- if (!list)
- {
- *bounds = fz_empty_rect;
- return fz_transform_rect(bounds, trm);
- }
-
- fz_concat(&ctm, &font->t3matrix, trm);
- dev = fz_new_bbox_device(ctx, bounds);
- fz_try(ctx)
- {
- fz_run_display_list(list, dev, &ctm, &fz_infinite_rect, NULL);
- }
- fz_always(ctx)
- {
- fz_free_device(dev);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
-
- return bounds;
-}
-
-fz_pixmap *
-fz_render_t3_glyph(fz_context *ctx, fz_font *font, int gid, const fz_matrix *trm, fz_colorspace *model, fz_irect scissor)
-{
- fz_display_list *list;
- fz_matrix ctm;
- fz_rect bounds;
- fz_irect bbox;
- fz_device *dev;
- fz_pixmap *glyph;
- fz_pixmap *result;
-
- if (gid < 0 || gid > 255)
- return NULL;
-
- list = font->t3lists[gid];
- if (!list)
- return NULL;
-
- if (font->t3flags[gid] & FZ_DEVFLAG_MASK)
- {
- if (font->t3flags[gid] & FZ_DEVFLAG_COLOR)
- fz_warn(ctx, "type3 glyph claims to be both masked and colored");
- model = NULL;
- }
- else if (font->t3flags[gid] & FZ_DEVFLAG_COLOR)
- {
- if (!model)
- fz_warn(ctx, "colored type3 glyph wanted in masked context");
- }
- else
- {
- fz_warn(ctx, "type3 glyph doesn't specify masked or colored");
- model = NULL; /* Treat as masked */
- }
-
- fz_expand_rect(fz_bound_glyph(ctx, font, gid, trm, &bounds), 1);
- fz_irect_from_rect(&bbox, &bounds);
- fz_intersect_irect(&bbox, &scissor);
-
- glyph = fz_new_pixmap_with_bbox(ctx, model ? model : fz_device_gray(ctx), &bbox);
- fz_clear_pixmap(ctx, glyph);
-
- fz_concat(&ctm, &font->t3matrix, trm);
- dev = fz_new_draw_device_type3(ctx, glyph);
- fz_run_display_list(list, dev, &ctm, &fz_infinite_rect, NULL);
- fz_free_device(dev);
-
- if (!model)
- {
- result = fz_alpha_from_gray(ctx, glyph, 0);
- fz_drop_pixmap(ctx, glyph);
- }
- else
- result = glyph;
-
- return result;
-}
-
-void
-fz_render_t3_glyph_direct(fz_context *ctx, fz_device *dev, fz_font *font, int gid, const fz_matrix *trm, void *gstate, int nested_depth)
-{
- fz_matrix ctm;
- void *contents;
-
- if (gid < 0 || gid > 255)
- return;
-
- contents = font->t3procs[gid];
- if (!contents)
- return;
-
- if (font->t3flags[gid] & FZ_DEVFLAG_MASK)
- {
- if (font->t3flags[gid] & FZ_DEVFLAG_COLOR)
- fz_warn(ctx, "type3 glyph claims to be both masked and colored");
- }
- else if (font->t3flags[gid] & FZ_DEVFLAG_COLOR)
- {
- }
- else
- {
- fz_warn(ctx, "type3 glyph doesn't specify masked or colored");
- }
-
- fz_concat(&ctm, &font->t3matrix, trm);
- font->t3run(font->t3doc, font->t3resources, contents, dev, &ctm, gstate, nested_depth);
-}
-
-#ifndef NDEBUG
-void
-fz_print_font(fz_context *ctx, FILE *out, fz_font *font)
-{
- fprintf(out, "font '%s' {\n", font->name);
-
- if (font->ft_face)
- {
- fprintf(out, "\tfreetype face %p\n", font->ft_face);
- if (font->ft_substitute)
- fprintf(out, "\tsubstitute font\n");
- }
-
- if (font->t3procs)
- {
- fprintf(out, "\ttype3 matrix [%g %g %g %g]\n",
- font->t3matrix.a, font->t3matrix.b,
- font->t3matrix.c, font->t3matrix.d);
-
- fprintf(out, "\ttype3 bbox [%g %g %g %g]\n",
- font->bbox.x0, font->bbox.y0,
- font->bbox.x1, font->bbox.y1);
- }
-
- fprintf(out, "}\n");
-}
-#endif
-
-fz_rect *
-fz_bound_glyph(fz_context *ctx, fz_font *font, int gid, const fz_matrix *trm, fz_rect *rect)
-{
- if (font->bbox_table && gid < font->bbox_count)
- {
- if (fz_is_infinite_rect(&font->bbox_table[gid]))
- {
- if (font->ft_face)
- fz_bound_ft_glyph(ctx, font, gid, &fz_identity, &font->bbox_table[gid]);
- else if (font->t3lists)
- fz_bound_t3_glyph(ctx, font, gid, &fz_identity, &font->bbox_table[gid]);
- else
- font->bbox_table[gid] = fz_empty_rect;
- }
- *rect = font->bbox_table[gid];
- }
- else
- {
- /* fall back to font bbox */
- *rect = font->bbox;
- }
-
- return fz_transform_rect(rect, trm);
-}
-
-fz_path *
-fz_outline_glyph(fz_context *ctx, fz_font *font, int gid, const fz_matrix *ctm)
-{
- if (!font->ft_face)
- return NULL;
- return fz_outline_ft_glyph(ctx, font, gid, ctm);
-}
-
-int fz_glyph_cacheable(fz_context *ctx, fz_font *font, int gid)
-{
- if (!font->t3procs || !font->t3flags || gid < 0 || gid >= font->bbox_count)
- return 1;
- return (font->t3flags[gid] & FZ_DEVFLAG_UNCACHEABLE) == 0;
-}
diff --git a/fitz/res_func.c b/fitz/res_func.c
deleted file mode 100644
index b5ba4815..00000000
--- a/fitz/res_func.c
+++ /dev/null
@@ -1,48 +0,0 @@
-#include "mupdf/fitz.h"
-
-void
-fz_eval_function(fz_context *ctx, fz_function *func, float *in_, int inlen, float *out_, int outlen)
-{
- float fakein[FZ_FN_MAXM];
- float fakeout[FZ_FN_MAXN];
- float *in = in_;
- float *out = out_;
-
- if (inlen < func->m)
- {
- in = fakein;
- memset(in, 0, sizeof(float) * func->m);
- memcpy(in, in_, sizeof(float) * inlen);
- }
-
- if (outlen < func->n)
- {
- out = fakeout;
- memset(out, 0, sizeof(float) * func->n);
- }
- else
- memset(out, 0, sizeof(float) * outlen);
-
- func->evaluate(ctx, func, in, out);
-
- if (outlen < func->n)
- memcpy(out_, out, sizeof(float) * outlen);
-}
-
-fz_function *
-fz_keep_function(fz_context *ctx, fz_function *func)
-{
- return (fz_function *)fz_keep_storable(ctx, &func->storable);
-}
-
-void
-fz_drop_function(fz_context *ctx, fz_function *func)
-{
- fz_drop_storable(ctx, &func->storable);
-}
-
-unsigned int
-fz_function_size(fz_function *func)
-{
- return (func ? func->size : 0);
-}
diff --git a/fitz/res_halftone.c b/fitz/res_halftone.c
deleted file mode 100644
index 15aebead..00000000
--- a/fitz/res_halftone.c
+++ /dev/null
@@ -1,202 +0,0 @@
-#include "mupdf/fitz.h"
-
-fz_halftone *
-fz_new_halftone(fz_context *ctx, int comps)
-{
- fz_halftone *ht;
- int i;
-
- ht = fz_malloc(ctx, sizeof(fz_halftone) + (comps-1)*sizeof(fz_pixmap *));
- ht->refs = 1;
- ht->n = comps;
- for (i = 0; i < comps; i++)
- ht->comp[i] = NULL;
-
- return ht;
-}
-
-fz_halftone *
-fz_keep_halftone(fz_context *ctx, fz_halftone *ht)
-{
- if (ht)
- ht->refs++;
- return ht;
-}
-
-void
-fz_drop_halftone(fz_context *ctx, fz_halftone *ht)
-{
- int i;
-
- if (!ht || --ht->refs != 0)
- return;
- for (i = 0; i < ht->n; i++)
- fz_drop_pixmap(ctx, ht->comp[i]);
- fz_free(ctx, ht);
-}
-
-/* Default mono halftone, lifted from Ghostscript. */
-/* The 0x00 entry has been changed to 0x01 to avoid problems with white
- * pixels appearing in the output; as we use < 0 should not appear in the
- * array. I think that gs scales this slighly and hence never actually uses
- * the raw values here. */
-static unsigned char mono_ht[] =
-{
- 0x0E, 0x8E, 0x2E, 0xAE, 0x06, 0x86, 0x26, 0xA6, 0x0C, 0x8C, 0x2C, 0xAC, 0x04, 0x84, 0x24, 0xA4,
- 0xCE, 0x4E, 0xEE, 0x6E, 0xC6, 0x46, 0xE6, 0x66, 0xCC, 0x4C, 0xEC, 0x6C, 0xC4, 0x44, 0xE4, 0x64,
- 0x3E, 0xBE, 0x1E, 0x9E, 0x36, 0xB6, 0x16, 0x96, 0x3C, 0xBC, 0x1C, 0x9C, 0x34, 0xB4, 0x14, 0x94,
- 0xFE, 0x7E, 0xDE, 0x5E, 0xF6, 0x76, 0xD6, 0x56, 0xFC, 0x7C, 0xDC, 0x5C, 0xF4, 0x74, 0xD4, 0x54,
- 0x01, 0x81, 0x21, 0xA1, 0x09, 0x89, 0x29, 0xA9, 0x03, 0x83, 0x23, 0xA3, 0x0B, 0x8B, 0x2B, 0xAB,
- 0xC1, 0x41, 0xE1, 0x61, 0xC9, 0x49, 0xE9, 0x69, 0xC3, 0x43, 0xE3, 0x63, 0xCB, 0x4B, 0xEB, 0x6B,
- 0x31, 0xB1, 0x11, 0x91, 0x39, 0xB9, 0x19, 0x99, 0x33, 0xB3, 0x13, 0x93, 0x3B, 0xBB, 0x1B, 0x9B,
- 0xF1, 0x71, 0xD1, 0x51, 0xF9, 0x79, 0xD9, 0x59, 0xF3, 0x73, 0xD3, 0x53, 0xFB, 0x7B, 0xDB, 0x5B,
- 0x0D, 0x8D, 0x2D, 0xAD, 0x05, 0x85, 0x25, 0xA5, 0x0F, 0x8F, 0x2F, 0xAF, 0x07, 0x87, 0x27, 0xA7,
- 0xCD, 0x4D, 0xED, 0x6D, 0xC5, 0x45, 0xE5, 0x65, 0xCF, 0x4F, 0xEF, 0x6F, 0xC7, 0x47, 0xE7, 0x67,
- 0x3D, 0xBD, 0x1D, 0x9D, 0x35, 0xB5, 0x15, 0x95, 0x3F, 0xBF, 0x1F, 0x9F, 0x37, 0xB7, 0x17, 0x97,
- 0xFD, 0x7D, 0xDD, 0x5D, 0xF5, 0x75, 0xD5, 0x55, 0xFF, 0x7F, 0xDF, 0x5F, 0xF7, 0x77, 0xD7, 0x57,
- 0x02, 0x82, 0x22, 0xA2, 0x0A, 0x8A, 0x2A, 0xAA, 0x01 /*0x00*/, 0x80, 0x20, 0xA0, 0x08, 0x88, 0x28, 0xA8,
- 0xC2, 0x42, 0xE2, 0x62, 0xCA, 0x4A, 0xEA, 0x6A, 0xC0, 0x40, 0xE0, 0x60, 0xC8, 0x48, 0xE8, 0x68,
- 0x32, 0xB2, 0x12, 0x92, 0x3A, 0xBA, 0x1A, 0x9A, 0x30, 0xB0, 0x10, 0x90, 0x38, 0xB8, 0x18, 0x98,
- 0xF2, 0x72, 0xD2, 0x52, 0xFA, 0x7A, 0xDA, 0x5A, 0xF0, 0x70, 0xD0, 0x50, 0xF8, 0x78, 0xD8, 0x58
-};
-
-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 */
- ht->comp[0] = fz_new_pixmap_with_data(ctx, NULL, 16, 16, mono_ht);
- return ht;
-}
-
-/* Finally, code to actually perform halftoning. */
-static void make_ht_line(unsigned char *buf, fz_halftone *ht, int x, int y, int w)
-{
- /* FIXME: There is a potential optimisation here; in the case where
- * the LCM of the halftone tile widths is smaller than w, we could
- * form just one 'LCM' run, then copy it repeatedly.
- */
- int k, n;
- n = ht->n;
- for (k = 0; k < n; k++)
- {
- fz_pixmap *tile = ht->comp[k];
- unsigned char *b = buf++;
- unsigned char *t;
- unsigned char *tbase;
- int px = x + tile->x;
- int py = y + tile->y;
- int tw = tile->w;
- int th = tile->h;
- int w2 = w;
- int len;
- px = px % tw;
- if (px < 0)
- px += tw;
- py = py % th;
- if (py < 0)
- py += th;
-
- assert(tile->n == 1);
-
- /* Left hand section; from x to tile width */
- tbase = tile->samples + (unsigned int)(py * tw);
- t = tbase + px;
- len = tw - px;
- if (len > w2)
- len = w2;
- w2 -= len;
- while (len--)
- {
- *b = *t++;
- b += n;
- }
-
- /* Centre section - complete copies */
- w2 -= tw;
- while (w2 >= 0)
- {
- len = tw;
- t = tbase;
- while (len--)
- {
- *b = *t++;
- b += n;
- }
- w2 -= tw;
- }
- w2 += tw;
-
- /* Right hand section - stragglers */
- t = tbase;
- while (w2--)
- {
- *b = *t++;
- b += n;
- }
- }
-}
-
-/* Inner mono thresholding code */
-static void do_threshold_1(unsigned char *ht_line, unsigned char *pixmap, unsigned char *out, int w)
-{
- int bit = 0x80;
- int h = 0;
-
- do
- {
- if (*pixmap < *ht_line++)
- h |= bit;
- pixmap += 2; /* Skip the alpha */
- bit >>= 1;
- if (bit == 0)
- {
- *out++ = h;
- h = 0;
- bit = 0x80;
- }
-
- }
- while (--w);
- if (bit != 0x80)
- *out++ = h;
-}
-
-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)
- return NULL;
-
- assert(pix->n == 2); /* Mono + Alpha */
-
- n = pix->n-1; /* Remove alpha */
- if (ht == NULL)
- {
- ht = fz_default_halftone(ctx, n);
- }
- ht_line = fz_malloc(ctx, pix->w * n);
- out = fz_new_bitmap(ctx, pix->w, pix->h, n, pix->xres, pix->yres);
- o = out->samples;
- p = pix->samples;
-
- h = pix->h;
- x = pix->x;
- y = pix->y;
- w = pix->w;
- ostride = out->stride;
- pstride = pix->w * pix->n;
- while (h--)
- {
- make_ht_line(ht_line, ht, x, y++, w);
- do_threshold_1(ht_line, p, o, w);
- o += ostride;
- p += pstride;
- }
- if (!ht_orig)
- fz_drop_halftone(ctx, ht);
- return out;
-}
diff --git a/fitz/res_image.c b/fitz/res_image.c
deleted file mode 100644
index 73b4bc28..00000000
--- a/fitz/res_image.c
+++ /dev/null
@@ -1,493 +0,0 @@
-#include "mupdf/fitz.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);
-}
-
-typedef struct fz_image_key_s fz_image_key;
-
-struct fz_image_key_s {
- int refs;
- fz_image *image;
- int l2factor;
-};
-
-static int
-fz_make_hash_image_key(fz_store_hash *hash, void *key_)
-{
- fz_image_key *key = (fz_image_key *)key_;
-
- hash->u.pi.ptr = key->image;
- hash->u.pi.i = key->l2factor;
- return 1;
-}
-
-static void *
-fz_keep_image_key(fz_context *ctx, void *key_)
-{
- fz_image_key *key = (fz_image_key *)key_;
-
- fz_lock(ctx, FZ_LOCK_ALLOC);
- key->refs++;
- fz_unlock(ctx, FZ_LOCK_ALLOC);
-
- return (void *)key;
-}
-
-static void
-fz_drop_image_key(fz_context *ctx, void *key_)
-{
- fz_image_key *key = (fz_image_key *)key_;
- int drop;
-
- if (key == NULL)
- return;
- fz_lock(ctx, FZ_LOCK_ALLOC);
- drop = --key->refs;
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- if (drop == 0)
- {
- fz_drop_image(ctx, key->image);
- fz_free(ctx, key);
- }
-}
-
-static int
-fz_cmp_image_key(void *k0_, void *k1_)
-{
- fz_image_key *k0 = (fz_image_key *)k0_;
- fz_image_key *k1 = (fz_image_key *)k1_;
-
- return k0->image == k1->image && k0->l2factor == k1->l2factor;
-}
-
-#ifndef NDEBUG
-static void
-fz_debug_image(FILE *out, void *key_)
-{
- fz_image_key *key = (fz_image_key *)key_;
-
- fprintf(out, "(image %d x %d sf=%d) ", key->image->w, key->image->h, key->l2factor);
-}
-#endif
-
-static fz_store_type fz_image_store_type =
-{
- fz_make_hash_image_key,
- fz_keep_image_key,
- fz_drop_image_key,
- fz_cmp_image_key,
-#ifndef NDEBUG
- fz_debug_image
-#endif
-};
-
-static void
-fz_mask_color_key(fz_pixmap *pix, int n, int *colorkey)
-{
- unsigned char *p = pix->samples;
- int len = pix->w * pix->h;
- int k, t;
- while (len--)
- {
- t = 1;
- for (k = 0; k < n; k++)
- if (p[k] < colorkey[k * 2] || p[k] > colorkey[k * 2 + 1])
- t = 0;
- if (t)
- for (k = 0; k < pix->n; k++)
- p[k] = 0;
- p += pix->n;
- }
-}
-
-fz_pixmap *
-fz_decomp_image_from_stream(fz_context *ctx, fz_stream *stm, fz_image *image, int in_line, int indexed, int l2factor, int native_l2factor)
-{
- fz_pixmap *tile = NULL;
- int stride, len, i;
- unsigned char *samples = NULL;
- int f = 1<<native_l2factor;
- int w = (image->w + f-1) >> native_l2factor;
- int h = (image->h + f-1) >> native_l2factor;
-
- fz_var(tile);
- fz_var(samples);
-
- fz_try(ctx)
- {
- tile = fz_new_pixmap(ctx, image->colorspace, w, h);
- tile->interpolate = image->interpolate;
-
- stride = (w * image->n * image->bpc + 7) / 8;
-
- samples = fz_malloc_array(ctx, h, stride);
-
- len = fz_read(stm, samples, h * stride);
- if (len < 0)
- {
- fz_throw(ctx, FZ_ERROR_GENERIC, "cannot read image data");
- }
-
- /* Make sure we read the EOF marker (for inline images only) */
- if (in_line)
- {
- unsigned char tbuf[512];
- fz_try(ctx)
- {
- int tlen = fz_read(stm, tbuf, sizeof tbuf);
- if (tlen > 0)
- fz_warn(ctx, "ignoring garbage at end of image");
- }
- fz_catch(ctx)
- {
- /* FIXME: TryLater? */
- fz_warn(ctx, "ignoring error at end of image");
- }
- }
-
- /* Pad truncated images */
- if (len < stride * h)
- {
- fz_warn(ctx, "padding truncated image");
- memset(samples + len, 0, stride * h - len);
- }
-
- /* Invert 1-bit image masks */
- if (image->imagemask)
- {
- /* 0=opaque and 1=transparent so we need to invert */
- unsigned char *p = samples;
- len = h * stride;
- for (i = 0; i < len; i++)
- p[i] = ~p[i];
- }
-
- fz_unpack_tile(tile, samples, image->n, image->bpc, stride, indexed);
-
- fz_free(ctx, samples);
- samples = NULL;
-
- if (image->usecolorkey)
- fz_mask_color_key(tile, image->n, image->colorkey);
-
- if (indexed)
- {
- fz_pixmap *conv;
- fz_decode_indexed_tile(tile, image->decode, (1 << image->bpc) - 1);
- conv = fz_expand_indexed_pixmap(ctx, tile);
- fz_drop_pixmap(ctx, tile);
- tile = conv;
- }
- else
- {
- fz_decode_tile(tile, image->decode);
- }
- }
- fz_always(ctx)
- {
- fz_close(stm);
- }
- fz_catch(ctx)
- {
- if (tile)
- fz_drop_pixmap(ctx, tile);
- fz_free(ctx, samples);
-
- fz_rethrow(ctx);
- }
-
- /* Now apply any extra subsampling required */
- if (l2factor - native_l2factor > 0)
- {
- if (l2factor - native_l2factor > 8)
- l2factor = native_l2factor + 8;
- fz_subsample_pixmap(ctx, tile, l2factor - native_l2factor);
- }
-
- return tile;
-}
-
-void
-fz_free_image(fz_context *ctx, fz_storable *image_)
-{
- fz_image *image = (fz_image *)image_;
-
- if (image == NULL)
- return;
- fz_drop_pixmap(ctx, image->tile);
- fz_free_compressed_buffer(ctx, image->buffer);
- fz_drop_colorspace(ctx, image->colorspace);
- fz_drop_image(ctx, image->mask);
- fz_free(ctx, image);
-}
-
-fz_pixmap *
-fz_image_get_pixmap(fz_context *ctx, fz_image *image, int w, int h)
-{
- fz_pixmap *tile;
- fz_stream *stm;
- int l2factor;
- fz_image_key key;
- int native_l2factor;
- int indexed;
- fz_image_key *keyp;
-
- /* Check for 'simple' images which are just pixmaps */
- if (image->buffer == NULL)
- {
- tile = image->tile;
- if (!tile)
- return NULL;
- return fz_keep_pixmap(ctx, tile); /* That's all we can give you! */
- }
-
- /* Ensure our expectations for tile size are reasonable */
- if (w > image->w)
- w = image->w;
- if (h > image->h)
- h = image->h;
-
- /* What is our ideal factor? */
- if (w == 0 || h == 0)
- l2factor = 0;
- else
- for (l2factor=0; image->w>>(l2factor+1) >= w && image->h>>(l2factor+1) >= h && l2factor < 8; l2factor++);
-
- /* Can we find any suitable tiles in the cache? */
- key.refs = 1;
- key.image = image;
- key.l2factor = l2factor;
- do
- {
- tile = fz_find_item(ctx, fz_free_pixmap_imp, &key, &fz_image_store_type);
- if (tile)
- return tile;
- key.l2factor--;
- }
- while (key.l2factor >= 0);
-
- /* We need to make a new one. */
- /* First check for ones that we can't decode using streams */
- switch (image->buffer->params.type)
- {
- case FZ_IMAGE_PNG:
- tile = fz_load_png(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
- break;
- case FZ_IMAGE_TIFF:
- tile = fz_load_tiff(ctx, image->buffer->buffer->data, image->buffer->buffer->len);
- break;
- default:
- native_l2factor = l2factor;
- stm = fz_open_image_decomp_stream(ctx, image->buffer, &native_l2factor);
-
- indexed = fz_colorspace_is_indexed(image->colorspace);
- tile = fz_decomp_image_from_stream(ctx, stm, image, 0, indexed, l2factor, native_l2factor);
- break;
- }
-
- /* Now we try to cache the pixmap. Any failure here will just result
- * in us not caching. */
- fz_var(keyp);
- fz_try(ctx)
- {
- fz_pixmap *existing_tile;
-
- keyp = fz_malloc_struct(ctx, fz_image_key);
- keyp->refs = 1;
- keyp->image = fz_keep_image(ctx, image);
- keyp->l2factor = l2factor;
- existing_tile = fz_store_item(ctx, keyp, tile, fz_pixmap_size(ctx, tile), &fz_image_store_type);
- if (existing_tile)
- {
- /* We already have a tile. This must have been produced by a
- * racing thread. We'll throw away ours and use that one. */
- fz_drop_pixmap(ctx, tile);
- tile = existing_tile;
- }
- }
- fz_always(ctx)
- {
- fz_drop_image_key(ctx, keyp);
- }
- fz_catch(ctx)
- {
- /* Do nothing */
- }
-
- return tile;
-}
-
-fz_image *
-fz_new_image_from_pixmap(fz_context *ctx, fz_pixmap *pixmap, fz_image *mask)
-{
- fz_image *image;
-
- assert(mask == NULL || mask->mask == NULL);
-
- fz_try(ctx)
- {
- image = fz_malloc_struct(ctx, fz_image);
- FZ_INIT_STORABLE(image, 1, fz_free_image);
- image->w = pixmap->w;
- image->h = pixmap->h;
- image->n = pixmap->n;
- image->colorspace = pixmap->colorspace;
- image->bpc = 8;
- image->buffer = NULL;
- image->get_pixmap = fz_image_get_pixmap;
- image->xres = pixmap->xres;
- image->yres = pixmap->yres;
- image->tile = pixmap;
- image->mask = mask;
- }
- fz_catch(ctx)
- {
- fz_drop_image(ctx, mask);
- fz_rethrow(ctx);
- }
- return image;
-}
-
-fz_image *
-fz_new_image(fz_context *ctx, int w, int h, int bpc, fz_colorspace *colorspace,
- int xres, int yres, int interpolate, int imagemask, float *decode,
- int *colorkey, fz_compressed_buffer *buffer, fz_image *mask)
-{
- fz_image *image;
-
- assert(mask == NULL || mask->mask == NULL);
-
- fz_try(ctx)
- {
- image = fz_malloc_struct(ctx, fz_image);
- FZ_INIT_STORABLE(image, 1, fz_free_image);
- image->get_pixmap = fz_image_get_pixmap;
- image->w = w;
- image->h = h;
- image->xres = xres;
- image->yres = yres;
- image->bpc = bpc;
- image->n = (colorspace ? colorspace->n : 1);
- image->colorspace = colorspace;
- image->interpolate = interpolate;
- image->imagemask = imagemask;
- image->usecolorkey = (colorkey != NULL);
- if (colorkey)
- memcpy(image->colorkey, colorkey, sizeof(int)*image->n*2);
- if (decode)
- memcpy(image->decode, decode, sizeof(float)*image->n*2);
- else
- {
- float maxval = fz_colorspace_is_indexed(colorspace) ? (1 << bpc) - 1 : 1;
- int i;
- for (i = 0; i < image->n; i++)
- {
- image->decode[2*i] = 0;
- image->decode[2*i+1] = maxval;
- }
- }
- image->mask = mask;
- image->buffer = buffer;
- }
- fz_catch(ctx)
- {
- fz_free_compressed_buffer(ctx, buffer);
- fz_rethrow(ctx);
- }
-
- return image;
-}
-
-fz_image *
-fz_new_image_from_data(fz_context *ctx, unsigned char *data, int len)
-{
- fz_buffer *buffer = NULL;
- fz_image *image;
-
- fz_var(buffer);
- fz_var(data);
-
- fz_try(ctx)
- {
- buffer = fz_new_buffer_from_data(ctx, data, len);
- data = NULL;
- image = fz_new_image_from_buffer(ctx, buffer);
- }
- fz_always(ctx)
- {
- fz_drop_buffer(ctx, buffer);
- }
- fz_catch(ctx)
- {
- fz_free(ctx, data);
- fz_rethrow(ctx);
- }
-
- return image;
-}
-
-fz_image *
-fz_new_image_from_buffer(fz_context *ctx, fz_buffer *buffer)
-{
- fz_compressed_buffer *bc = NULL;
- int w, h, xres, yres;
- fz_colorspace *cspace;
- int len = buffer->len;
- unsigned char *buf = buffer->data;
-
- fz_var(bc);
-
- fz_try(ctx)
- {
- if (len < 8)
- fz_throw(ctx, FZ_ERROR_GENERIC, "unknown image file format");
-
- bc = fz_malloc_struct(ctx, fz_compressed_buffer);
- bc->buffer = fz_keep_buffer(ctx, buffer);
-
- if (buf[0] == 0xff && buf[1] == 0xd8)
- {
- bc->params.type = FZ_IMAGE_JPEG;
- bc->params.u.jpeg.color_transform = -1;
- fz_load_jpeg_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
- }
- else if (memcmp(buf, "\211PNG\r\n\032\n", 8) == 0)
- {
- bc->params.type = FZ_IMAGE_PNG;
- fz_load_png_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
- }
- else if (memcmp(buf, "II", 2) == 0 && buf[2] == 0xBC)
- fz_throw(ctx, FZ_ERROR_GENERIC, "JPEG-XR codec is not available");
- else if (memcmp(buf, "MM", 2) == 0 || memcmp(buf, "II", 2) == 0)
- {
- bc->params.type = FZ_IMAGE_TIFF;
- fz_load_tiff_info(ctx, buf, len, &w, &h, &xres, &yres, &cspace);
- }
- else
- fz_throw(ctx, FZ_ERROR_GENERIC, "unknown image file format");
- }
- fz_catch(ctx)
- {
- fz_free_compressed_buffer(ctx, bc);
- fz_rethrow(ctx);
- }
-
- return fz_new_image(ctx, w, h, 8, cspace, xres, yres, 0, 0, NULL, NULL, bc, NULL);
-}
diff --git a/fitz/res_path.c b/fitz/res_path.c
deleted file mode 100644
index cbdfc7bc..00000000
--- a/fitz/res_path.c
+++ /dev/null
@@ -1,507 +0,0 @@
-#include <assert.h>
-#include "mupdf/fitz.h"
-
-fz_path *
-fz_new_path(fz_context *ctx)
-{
- fz_path *path;
-
- path = fz_malloc_struct(ctx, fz_path);
- path->len = 0;
- path->cap = 0;
- path->items = NULL;
- path->last = -1;
-
- return path;
-}
-
-fz_path *
-fz_clone_path(fz_context *ctx, fz_path *old)
-{
- fz_path *path;
-
- assert(old);
- path = fz_malloc_struct(ctx, fz_path);
- fz_try(ctx)
- {
- path->len = old->len;
- path->cap = old->len;
- path->items = fz_malloc_array(ctx, path->cap, sizeof(fz_path_item));
- memcpy(path->items, old->items, sizeof(fz_path_item) * path->len);
- }
- fz_catch(ctx)
- {
- fz_free(ctx, path);
- fz_rethrow(ctx);
- }
-
- return path;
-}
-
-void
-fz_free_path(fz_context *ctx, fz_path *path)
-{
- if (path == NULL)
- return;
- fz_free(ctx, path->items);
- fz_free(ctx, path);
-}
-
-static void
-grow_path(fz_context *ctx, fz_path *path, int n)
-{
- int newcap = path->cap;
- if (path->len + n <= path->cap)
- {
- path->last = path->len;
- return;
- }
- while (path->len + n > newcap)
- newcap = newcap + 36;
- path->items = fz_resize_array(ctx, path->items, newcap, sizeof(fz_path_item));
- path->cap = newcap;
- path->last = path->len;
-}
-
-fz_point
-fz_currentpoint(fz_context *ctx, fz_path *path)
-{
- fz_point c, m;
- int i;
-
- c.x = c.y = m.x = m.y = 0;
- i = 0;
-
- while (i < path->len)
- {
- switch (path->items[i++].k)
- {
- case FZ_MOVETO:
- m.x = c.x = path->items[i++].v;
- m.y = c.y = path->items[i++].v;
- break;
- case FZ_LINETO:
- c.x = path->items[i++].v;
- c.y = path->items[i++].v;
- break;
- case FZ_CURVETO:
- i += 4;
- c.x = path->items[i++].v;
- c.y = path->items[i++].v;
- break;
- case FZ_CLOSE_PATH:
- c = m;
- }
- }
-
- return c;
-}
-
-void
-fz_moveto(fz_context *ctx, fz_path *path, float x, float y)
-{
- if (path->last >= 0 && path->items[path->last].k == FZ_MOVETO)
- {
- /* No point in having MOVETO then MOVETO */
- path->len = path->last;
- }
- grow_path(ctx, path, 3);
- path->items[path->len++].k = FZ_MOVETO;
- path->items[path->len++].v = x;
- path->items[path->len++].v = y;
-}
-
-void
-fz_lineto(fz_context *ctx, fz_path *path, float x, float y)
-{
- float x0, y0;
-
- if (path->last < 0)
- {
- fz_warn(ctx, "lineto with no current point");
- return;
- }
- if (path->items[path->last].k == FZ_CLOSE_PATH)
- {
- x0 = path->items[path->last-2].v;
- y0 = path->items[path->last-1].v;
- }
- else
- {
- x0 = path->items[path->len-2].v;
- y0 = path->items[path->len-1].v;
- }
- /* Anything other than MoveTo followed by LineTo the same place is a nop */
- if (path->items[path->last].k != FZ_MOVETO && x0 == x && y0 == y)
- return;
- grow_path(ctx, path, 3);
- path->items[path->len++].k = FZ_LINETO;
- path->items[path->len++].v = x;
- path->items[path->len++].v = y;
-}
-
-void
-fz_curveto(fz_context *ctx, fz_path *path,
- float x1, float y1,
- float x2, float y2,
- float x3, float y3)
-{
- float x0, y0;
-
- if (path->last < 0)
- {
- fz_warn(ctx, "curveto with no current point");
- return;
- }
- if (path->items[path->last].k == FZ_CLOSE_PATH)
- {
- x0 = path->items[path->last-2].v;
- y0 = path->items[path->last-1].v;
- }
- else
- {
- x0 = path->items[path->len-2].v;
- y0 = path->items[path->len-1].v;
- }
-
- /* Check for degenerate cases: */
- if (x0 == x1 && y0 == y1)
- {
- if (x2 == x3 && y2 == y3)
- {
- /* If (x1,y1)==(x2,y2) and prev wasn't a moveto, then skip */
- if (x1 == x2 && y1 == y2 && path->items[path->last].k != FZ_MOVETO)
- return;
- /* Otherwise a line will suffice */
- fz_lineto(ctx, path, x3, y3);
- return;
- }
- if (x1 == x2 && y1 == y2)
- {
- /* A line will suffice */
- fz_lineto(ctx, path, x3, y3);
- return;
- }
- }
- else if (x1 == x2 && y1 == y2 && x2 == x3 && y2 == y3)
- {
- /* A line will suffice */
- fz_lineto(ctx, path, x3, y3);
- return;
- }
-
- grow_path(ctx, path, 7);
- path->items[path->len++].k = FZ_CURVETO;
- path->items[path->len++].v = x1;
- path->items[path->len++].v = y1;
- path->items[path->len++].v = x2;
- path->items[path->len++].v = y2;
- path->items[path->len++].v = x3;
- path->items[path->len++].v = y3;
-}
-
-void
-fz_curvetov(fz_context *ctx, fz_path *path, float x2, float y2, float x3, float y3)
-{
- float x1, y1;
- if (path->last < 0)
- {
- fz_warn(ctx, "curvetov with no current point");
- return;
- }
- if (path->items[path->last].k == FZ_CLOSE_PATH)
- {
- x1 = path->items[path->last-2].v;
- y1 = path->items[path->last-1].v;
- }
- else
- {
- x1 = path->items[path->len-2].v;
- y1 = path->items[path->len-1].v;
- }
- fz_curveto(ctx, path, x1, y1, x2, y2, x3, y3);
-}
-
-void
-fz_curvetoy(fz_context *ctx, fz_path *path, float x1, float y1, float x3, float y3)
-{
- fz_curveto(ctx, path, x1, y1, x3, y3, x3, y3);
-}
-
-void
-fz_closepath(fz_context *ctx, fz_path *path)
-{
- if (path->last < 0)
- {
- fz_warn(ctx, "closepath with no current point");
- return;
- }
- /* CLOSE following a CLOSE is a NOP */
- if (path->items[path->last].k == FZ_CLOSE_PATH)
- return;
- grow_path(ctx, path, 1);
- path->items[path->len++].k = FZ_CLOSE_PATH;
-}
-
-static inline fz_rect *bound_expand(fz_rect *r, const fz_point *p)
-{
- if (p->x < r->x0) r->x0 = p->x;
- if (p->y < r->y0) r->y0 = p->y;
- if (p->x > r->x1) r->x1 = p->x;
- if (p->y > r->y1) r->y1 = p->y;
- return r;
-}
-
-fz_rect *
-fz_bound_path(fz_context *ctx, fz_path *path, const fz_stroke_state *stroke, const fz_matrix *ctm, fz_rect *r)
-{
- fz_point p;
- int i = 0;
-
- /* If the path is empty, return the empty rectangle here - don't wait
- * for it to be expanded in the stroked case below. */
- if (path->len == 0)
- {
- *r = fz_empty_rect;
- return r;
- }
- /* A path must start with a moveto - and if that's all there is
- * then the path is empty. */
- if (path->len == 3)
- {
- *r = fz_empty_rect;
- return r;
- }
-
- p.x = path->items[1].v;
- p.y = path->items[2].v;
- fz_transform_point(&p, ctm);
- r->x0 = r->x1 = p.x;
- r->y0 = r->y1 = p.y;
-
- while (i < path->len)
- {
- switch (path->items[i++].k)
- {
- case FZ_CURVETO:
- p.x = path->items[i++].v;
- p.y = path->items[i++].v;
- bound_expand(r, fz_transform_point(&p, ctm));
- p.x = path->items[i++].v;
- p.y = path->items[i++].v;
- bound_expand(r, fz_transform_point(&p, ctm));
- p.x = path->items[i++].v;
- p.y = path->items[i++].v;
- bound_expand(r, fz_transform_point(&p, ctm));
- break;
- case FZ_MOVETO:
- if (i + 2 == path->len)
- {
- /* Trailing Moveto - cannot affect bbox */
- i += 2;
- break;
- }
- /* fallthrough */
- case FZ_LINETO:
- p.x = path->items[i++].v;
- p.y = path->items[i++].v;
- bound_expand(r, fz_transform_point(&p, ctm));
- break;
- case FZ_CLOSE_PATH:
- break;
- }
- }
-
- if (stroke)
- {
- fz_adjust_rect_for_stroke(r, stroke, ctm);
- }
-
- return r;
-}
-
-fz_rect *
-fz_adjust_rect_for_stroke(fz_rect *r, const fz_stroke_state *stroke, const fz_matrix *ctm)
-{
- float expand;
-
- if (!stroke)
- return r;
-
- expand = stroke->linewidth;
- if (expand == 0)
- expand = 1.0f;
- expand *= fz_matrix_max_expansion(ctm);
- if ((stroke->linejoin == FZ_LINEJOIN_MITER || stroke->linejoin == FZ_LINEJOIN_MITER_XPS) && stroke->miterlimit > 1)
- expand *= stroke->miterlimit;
-
- r->x0 -= expand;
- r->y0 -= expand;
- r->x1 += expand;
- r->y1 += expand;
- return r;
-}
-
-void
-fz_transform_path(fz_context *ctx, fz_path *path, const fz_matrix *ctm)
-{
- int k, i = 0;
-
- while (i < path->len)
- {
- switch (path->items[i++].k)
- {
- case FZ_CURVETO:
- for (k = 0; k < 3; k++)
- {
- fz_transform_point((fz_point *)(void *)&path->items[i].v, ctm);
- i += 2;
- }
- break;
- case FZ_MOVETO:
- case FZ_LINETO:
- fz_transform_point((fz_point *)(void *)&path->items[i].v, ctm);
- i += 2;
- break;
- case FZ_CLOSE_PATH:
- break;
- }
- }
-}
-
-#ifndef NDEBUG
-void
-fz_print_path(fz_context *ctx, FILE *out, fz_path *path, int indent)
-{
- float x, y;
- int i = 0;
- int n;
- while (i < path->len)
- {
- for (n = 0; n < indent; n++)
- fputc(' ', out);
- switch (path->items[i++].k)
- {
- case FZ_MOVETO:
- x = path->items[i++].v;
- y = path->items[i++].v;
- fprintf(out, "%g %g m\n", x, y);
- break;
- case FZ_LINETO:
- x = path->items[i++].v;
- y = path->items[i++].v;
- fprintf(out, "%g %g l\n", x, y);
- break;
- case FZ_CURVETO:
- x = path->items[i++].v;
- y = path->items[i++].v;
- fprintf(out, "%g %g ", x, y);
- x = path->items[i++].v;
- y = path->items[i++].v;
- fprintf(out, "%g %g ", x, y);
- x = path->items[i++].v;
- y = path->items[i++].v;
- fprintf(out, "%g %g c\n", x, y);
- break;
- case FZ_CLOSE_PATH:
- fprintf(out, "h\n");
- break;
- }
- }
-}
-#endif
-
-fz_stroke_state *
-fz_keep_stroke_state(fz_context *ctx, fz_stroke_state *stroke)
-{
- if (!stroke)
- return NULL;
-
- fz_lock(ctx, FZ_LOCK_ALLOC);
- if (stroke->refs > 0)
- stroke->refs++;
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- return stroke;
-}
-
-void
-fz_drop_stroke_state(fz_context *ctx, fz_stroke_state *stroke)
-{
- int drop;
-
- if (!stroke)
- return;
-
- fz_lock(ctx, FZ_LOCK_ALLOC);
- drop = (stroke->refs > 0 ? --stroke->refs == 0 : 0);
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- if (drop)
- fz_free(ctx, stroke);
-}
-
-fz_stroke_state *
-fz_new_stroke_state_with_len(fz_context *ctx, int len)
-{
- fz_stroke_state *state;
-
- len -= nelem(state->dash_list);
- if (len < 0)
- len = 0;
-
- state = Memento_label(fz_malloc(ctx, sizeof(*state) + sizeof(state->dash_list[0]) * len), "fz_stroke_state");
- state->refs = 1;
- state->start_cap = FZ_LINECAP_BUTT;
- state->dash_cap = FZ_LINECAP_BUTT;
- state->end_cap = FZ_LINECAP_BUTT;
- state->linejoin = FZ_LINEJOIN_MITER;
- state->linewidth = 1;
- state->miterlimit = 10;
- state->dash_phase = 0;
- state->dash_len = 0;
- memset(state->dash_list, 0, sizeof(state->dash_list[0]) * (len + nelem(state->dash_list)));
-
- return state;
-}
-
-fz_stroke_state *
-fz_new_stroke_state(fz_context *ctx)
-{
- return fz_new_stroke_state_with_len(ctx, 0);
-}
-
-fz_stroke_state *
-fz_unshare_stroke_state_with_len(fz_context *ctx, fz_stroke_state *shared, int len)
-{
- int single, unsize, shsize, shlen, drop;
- fz_stroke_state *unshared;
-
- fz_lock(ctx, FZ_LOCK_ALLOC);
- single = (shared->refs == 1);
- fz_unlock(ctx, FZ_LOCK_ALLOC);
-
- shlen = shared->dash_len - nelem(shared->dash_list);
- if (shlen < 0)
- shlen = 0;
- shsize = sizeof(*shared) + sizeof(shared->dash_list[0]) * shlen;
- len -= nelem(shared->dash_list);
- if (len < 0)
- len = 0;
- if (single && shlen >= len)
- return shared;
- unsize = sizeof(*unshared) + sizeof(unshared->dash_list[0]) * len;
- unshared = Memento_label(fz_malloc(ctx, unsize), "fz_stroke_state");
- memcpy(unshared, shared, (shsize > unsize ? unsize : shsize));
- unshared->refs = 1;
- fz_lock(ctx, FZ_LOCK_ALLOC);
- drop = (shared->refs > 0 ? --shared->refs == 0 : 0);
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- if (drop)
- fz_free(ctx, shared);
- return unshared;
-}
-
-fz_stroke_state *
-fz_unshare_stroke_state(fz_context *ctx, fz_stroke_state *shared)
-{
- return fz_unshare_stroke_state_with_len(ctx, shared, shared->dash_len);
-}
diff --git a/fitz/res_pcl.c b/fitz/res_pcl.c
deleted file mode 100644
index eae5dad2..00000000
--- a/fitz/res_pcl.c
+++ /dev/null
@@ -1,856 +0,0 @@
-#include "mupdf/fitz.h"
-
-/* Lifted from ghostscript gdevjlm.h */
-/*
- * The notion that there is such a thing as a "PCL printer" is a fiction: no
- * two "PCL" printers, even at the same PCL level, have identical command
- * sets. (The H-P documentation isn't fully accurate either; for example,
- * it doesn't reveal that the DeskJet printers implement anything beyond PCL
- * 3.)
- *
- * This file contains feature definitions for a generic monochrome PCL
- * driver (gdevdljm.c), and the specific feature values for all such
- * printers that Ghostscript currently supports.
- */
-
-/* Printer spacing capabilities. Include at most one of these. */
-#define PCL_NO_SPACING 0 /* no vertical spacing capability, must be 0 */
-#define PCL3_SPACING 1 /* <ESC>*p+<n>Y (PCL 3) */
-#define PCL4_SPACING 2 /* <ESC>*b<n>Y (PCL 4) */
-#define PCL5_SPACING 4 /* <ESC>*b<n>Y and clear seed row (PCL 5) */
-/* The following is only used internally. */
-#define PCL_ANY_SPACING \
- (PCL3_SPACING | PCL4_SPACING | PCL5_SPACING)
-
-/* Individual printer properties. Any subset of these may be included. */
-#define PCL_MODE_2_COMPRESSION 8 /* compression mode 2 supported */
- /* (PCL 4) */
-#define PCL_MODE_3_COMPRESSION 16 /* compression modes 2 & 3 supported */
- /* (PCL 5) */
-#define PCL_END_GRAPHICS_DOES_RESET 32 /* <esc>*rB resets all parameters */
-#define PCL_HAS_DUPLEX 64 /* <esc>&l<duplex>S supported */
-#define PCL_CAN_SET_PAPER_SIZE 128 /* <esc>&l<sizecode>A supported */
-#define PCL_CAN_PRINT_COPIES 256 /* <esc>&l<copies>X supported */
-#define HACK__IS_A_LJET4PJL 512
-#define HACK__IS_A_OCE9050 1024
-
-/* Shorthands for the most common spacing/compression combinations. */
-#define PCL_MODE0 PCL3_SPACING
-#define PCL_MODE0NS PCL_NO_SPACING
-#define PCL_MODE2 (PCL4_SPACING | PCL_MODE_2_COMPRESSION)
-#define PCL_MODE2P (PCL_NO_SPACING | PCL_MODE_2_COMPRESSION)
-#define PCL_MODE3 (PCL5_SPACING | PCL_MODE_3_COMPRESSION)
-#define PCL_MODE3NS (PCL_NO_SPACING | PCL_MODE_3_COMPRESSION)
-
-#define MIN_SKIP_LINES 7
-static const char *const from2to3 = "\033*b3M";
-static const char *const from3to2 = "\033*b2M";
-static const int penalty_from2to3 = 5; /* strlen(from2to3); */
-static const int penalty_from3to2 = 5; /* strlen(from3to2); */
-
-/* H-P DeskJet */
-static const fz_pcl_options fz_pcl_options_ljet4 =
-{
- (PCL_MODE2 | PCL_END_GRAPHICS_DOES_RESET | PCL_CAN_SET_PAPER_SIZE),
- "\033&k1W\033*b2M",
- "\033&k1W\033*b2M"
-};
-
-/* H-P DeskJet 500 */
-static const fz_pcl_options fz_pcl_options_dj500 =
-{
- (PCL_MODE3 | PCL_END_GRAPHICS_DOES_RESET | PCL_CAN_SET_PAPER_SIZE),
- "\033&k1W",
- "\033&k1W"
-};
-
-/* Kyocera FS-600 */
-static const fz_pcl_options fz_pcl_options_fs600 =
-{
- (PCL_MODE3 | PCL_CAN_SET_PAPER_SIZE | PCL_CAN_PRINT_COPIES),
- "\033*r0F\033&u%dD",
- "\033*r0F\033&u%dD"
-};
-
-/* H-P original LaserJet */
-/* H-P LaserJet Plus */
-static const fz_pcl_options fz_pcl_options_lj =
-{
- (PCL_MODE0),
- "\033*b0M",
- "\033*b0M"
-};
-
-/* H-P LaserJet IIp, IId */
-static const fz_pcl_options fz_pcl_options_lj2 =
-{
- (PCL_MODE2P | PCL_CAN_SET_PAPER_SIZE),
- "\033*r0F\033*b2M",
- "\033*r0F\033*b2M"
-};
-
-/* H-P LaserJet III* */
-static const fz_pcl_options fz_pcl_options_lj3 =
-{
- (PCL_MODE3 | PCL_CAN_SET_PAPER_SIZE | PCL_CAN_PRINT_COPIES),
- "\033&l-180u36Z\033*r0F",
- "\033&l-180u36Z\033*r0F"
-};
-
-/* H-P LaserJet IIId */
-static const fz_pcl_options fz_pcl_options_lj3d =
-{
- (PCL_MODE3 | PCL_HAS_DUPLEX | PCL_CAN_SET_PAPER_SIZE | PCL_CAN_PRINT_COPIES),
- "\033&l-180u36Z\033*r0F",
- "\033&l180u36Z\033*r0F"
-};
-
-/* H-P LaserJet 4 */
-static const fz_pcl_options fz_pcl_options_lj4 =
-{
- (PCL_MODE3 | PCL_CAN_SET_PAPER_SIZE | PCL_CAN_PRINT_COPIES),
- "\033&l-180u36Z\033*r0F\033&u%dD",
- "\033&l-180u36Z\033*r0F\033&u%dD"
-};
-
-/* H-P LaserJet 4 PL */
-static const fz_pcl_options fz_pcl_options_lj4pl =
-{
- (PCL_MODE3 | PCL_CAN_SET_PAPER_SIZE | PCL_CAN_PRINT_COPIES | HACK__IS_A_LJET4PJL),
- "\033&l-180u36Z\033*r0F\033&u%dD",
- "\033&l-180u36Z\033*r0F\033&u%dD"
-};
-
-/* H-P LaserJet 4d */
-static const fz_pcl_options fz_pcl_options_lj4d =
-{
- (PCL_MODE3 | PCL_HAS_DUPLEX | PCL_CAN_SET_PAPER_SIZE | PCL_CAN_PRINT_COPIES),
- "\033&l-180u36Z\033*r0F\033&u%dD",
- "\033&l180u36Z\033*r0F\033&u%dD"
-};
-
-/* H-P 2563B line printer */
-static const fz_pcl_options fz_pcl_options_lp2563b =
-{
- (PCL_MODE0NS | PCL_CAN_SET_PAPER_SIZE),
- "\033*b0M",
- "\033*b0M"
-};
-
-/* OCE 9050 line printer */
-static const fz_pcl_options fz_pcl_options_oce9050 =
-{
- (PCL_MODE3NS | PCL_CAN_SET_PAPER_SIZE | HACK__IS_A_OCE9050),
- "\033*b0M",
- "\033*b0M"
-};
-
-static void copy_opts(fz_pcl_options *dst, const fz_pcl_options *src)
-{
- if (dst)
- *dst = *src;
-}
-
-void fz_pcl_preset(fz_context *ctx, fz_pcl_options *opts, const char *preset)
-{
- if (preset == NULL || *preset == 0 || !strcmp(preset, "ljet4"))
- copy_opts(opts, &fz_pcl_options_ljet4);
- else if (!strcmp(preset, "dj500"))
- copy_opts(opts, &fz_pcl_options_dj500);
- else if (!strcmp(preset, "fs600"))
- copy_opts(opts, &fz_pcl_options_fs600);
- else if (!strcmp(preset, "lj"))
- copy_opts(opts, &fz_pcl_options_lj);
- else if (!strcmp(preset, "lj2"))
- copy_opts(opts, &fz_pcl_options_lj2);
- else if (!strcmp(preset, "lj3"))
- copy_opts(opts, &fz_pcl_options_lj3);
- else if (!strcmp(preset, "lj3d"))
- copy_opts(opts, &fz_pcl_options_lj3d);
- else if (!strcmp(preset, "lj4"))
- copy_opts(opts, &fz_pcl_options_lj4);
- else if (!strcmp(preset, "lj4pl"))
- copy_opts(opts, &fz_pcl_options_lj4pl);
- else if (!strcmp(preset, "lj4d"))
- copy_opts(opts, &fz_pcl_options_lj4d);
- else if (!strcmp(preset, "lp2563b"))
- copy_opts(opts, &fz_pcl_options_lp2563b);
- else if (!strcmp(preset, "oce9050"))
- copy_opts(opts, &fz_pcl_options_oce9050);
- else
- fz_throw(ctx, FZ_ERROR_GENERIC, "Unknown preset '%s'", preset);
-}
-
-void fz_pcl_option(fz_context *ctx, fz_pcl_options *opts, const char *option, int val)
-{
- if (opts == NULL)
- return;
-
- if (!strcmp(option, "spacing"))
- {
- switch (val)
- {
- case 0:
- opts->features &= ~PCL_ANY_SPACING;
- break;
- case 1:
- opts->features = (opts->features & ~PCL_ANY_SPACING) | PCL3_SPACING;
- break;
- case 2:
- opts->features = (opts->features & ~PCL_ANY_SPACING) | PCL4_SPACING;
- break;
- case 3:
- opts->features = (opts->features & ~PCL_ANY_SPACING) | PCL5_SPACING;
- break;
- default:
- fz_throw(ctx, FZ_ERROR_GENERIC, "Unsupported PCL spacing %d (0-3 only)", val);
- }
- }
- else if (!strcmp(option, "mode2"))
- {
- if (val == 0)
- opts->features &= ~PCL_MODE_2_COMPRESSION;
- else if (val == 1)
- opts->features |= PCL_MODE_2_COMPRESSION;
- else
- fz_throw(ctx, FZ_ERROR_GENERIC, "Expected 0 or 1 for mode2 value");
- }
- else if (!strcmp(option, "mode3"))
- {
- if (val == 0)
- opts->features &= ~PCL_MODE_3_COMPRESSION;
- else if (val == 1)
- opts->features |= PCL_MODE_3_COMPRESSION;
- else
- fz_throw(ctx, FZ_ERROR_GENERIC, "Expected 0 or 1 for mode3 value");
- }
- else if (!strcmp(option, "eog_reset"))
- {
- if (val == 0)
- opts->features &= ~PCL_END_GRAPHICS_DOES_RESET;
- else if (val == 1)
- opts->features |= PCL_END_GRAPHICS_DOES_RESET;
- else
- fz_throw(ctx, FZ_ERROR_GENERIC, "Expected 0 or 1 for eog_reset value");
- }
- else if (!strcmp(option, "has_duplex"))
- {
- if (val == 0)
- opts->features &= ~PCL_HAS_DUPLEX;
- else if (val == 1)
- opts->features |= PCL_HAS_DUPLEX;
- else
- fz_throw(ctx, FZ_ERROR_GENERIC, "Expected 0 or 1 for has_duplex value");
- }
- else if (!strcmp(option, "has_papersize"))
- {
- if (val == 0)
- opts->features &= ~PCL_CAN_SET_PAPER_SIZE;
- else if (val == 1)
- opts->features |= PCL_CAN_SET_PAPER_SIZE;
- else
- fz_throw(ctx, FZ_ERROR_GENERIC, "Expected 0 or 1 for has_papersize value");
- }
- else if (!strcmp(option, "has_copies"))
- {
- if (val == 0)
- opts->features &= ~PCL_CAN_PRINT_COPIES;
- else if (val == 1)
- opts->features |= PCL_CAN_PRINT_COPIES;
- else
- fz_throw(ctx, FZ_ERROR_GENERIC, "Expected 0 or 1 for has_papersize value");
- }
- else if (!strcmp(option, "is_ljet4pjl"))
- {
- if (val == 0)
- opts->features &= ~HACK__IS_A_LJET4PJL;
- else if (val == 1)
- opts->features |= HACK__IS_A_LJET4PJL;
- else
- fz_throw(ctx, FZ_ERROR_GENERIC, "Expected 0 or 1 for is_ljet4pjl value");
- }
- else if (!strcmp(option, "is_oce9050"))
- {
- if (val == 0)
- opts->features &= ~HACK__IS_A_OCE9050;
- else if (val == 1)
- opts->features |= HACK__IS_A_OCE9050;
- else
- fz_throw(ctx, FZ_ERROR_GENERIC, "Expected 0 or 1 for is_oce9050 value");
- }
- else
- fz_throw(ctx, FZ_ERROR_GENERIC, "Unknown pcl option '%s'", option);
-}
-
-static void
-make_init(fz_pcl_options *pcl, char *buf, unsigned long len, const char *str, int res)
-{
- int paper_source = -1;
-
- snprintf(buf, len, str, res);
-
- if (pcl->manual_feed_set && pcl->manual_feed)
- paper_source = 2;
- else if (pcl->media_position_set && pcl->media_position >= 0)
- paper_source = pcl->media_position;
- if (paper_source >= 0)
- {
- char buf2[40];
- snprintf(buf2, sizeof(buf2), "\033&l%dH", paper_source);
- strncat(buf, buf2, len);
- }
-}
-
-static void
-pcl_header(fz_output *out, fz_pcl_options *pcl, int num_copies, int xres)
-{
- char odd_page_init[80];
- char even_page_init[80];
-
- make_init(pcl, odd_page_init, sizeof(odd_page_init), pcl->odd_page_init, xres);
- make_init(pcl, even_page_init, sizeof(even_page_init), pcl->even_page_init, xres);
-
- if (pcl->page_count == 0)
- {
- if (pcl->features & HACK__IS_A_LJET4PJL)
- fz_puts(out, "\033%-12345X@PJL\r\n@PJL ENTER LANGUAGE = PCL\r\n");
- fz_puts(out, "\033E"); /* reset printer */
- /* If the printer supports it, set the paper size */
- /* based on the actual requested size. */
- if (pcl->features & PCL_CAN_SET_PAPER_SIZE)
- fz_printf(out, "\033&l%dA", pcl->paper_size);
- /* If printer can duplex, set duplex mode appropriately. */
- if (pcl->features & PCL_HAS_DUPLEX)
- {
- if (pcl->duplex_set)
- {
- if (pcl->duplex)
- {
- if (!pcl->tumble)
- fz_puts(out, "\033&l1S");
- else
- fz_puts(out, "\033&l2S");
- }
- else
- fz_puts(out, "\033&l0S");
- }
- else
- {
- /* default to duplex for this printer */
- fz_puts(out, "\033&l1S");
- }
- }
- }
-
- /* Put out per-page initialization. */
- /* in duplex mode the sheet is already in process, so there are some
- * commands which must not be sent to the printer for the 2nd page,
- * as this commands will cause the printer to eject the sheet with
- * only the 1st page printed. This commands are:
- * \033&l%dA (setting paper size)
- * \033&l%dH (setting paper tray)
- * in simplex mode we set this parameters for each page,
- * in duplex mode we set this parameters for each odd page
- */
-
- if ((pcl->features & PCL_HAS_DUPLEX) && pcl->duplex_set && pcl->duplex)
- {
- /* We are printing duplex, so change margins as needed */
- if (((pcl->page_count/num_copies)%2) == 0)
- {
- if (pcl->page_count != 0 && (pcl->features & PCL_CAN_SET_PAPER_SIZE))
- {
- fz_printf(out, "\033&l%dA", pcl->paper_size);
- }
- fz_puts(out, "\033&l0o0l0E");
- fz_puts(out, pcl->odd_page_init);
- }
- else
- fz_puts(out, pcl->even_page_init);
- }
- else
- {
- if (pcl->features & PCL_CAN_SET_PAPER_SIZE)
- {
- fz_printf(out, "\033&l%dA", pcl->paper_size);
- }
- fz_puts(out, "\033&l0o0l0E");
- fz_puts(out, pcl->odd_page_init);
- }
-
- fz_printf(out, "\033&l%dX", num_copies); /* # of copies */
-
- /* End raster graphics, position cursor at top. */
- fz_puts(out, "\033*rB\033*p0x0Y");
-
- /* The DeskJet and DeskJet Plus reset everything upon */
- /* receiving \033*rB, so we must reinitialize graphics mode. */
- if (pcl->features & PCL_END_GRAPHICS_DOES_RESET)
- {
- fz_puts(out, pcl->odd_page_init); /* Assume this does the right thing */
- fz_printf(out, "\033&l%dX", num_copies); /* # of copies */
- }
-
- /* Set resolution. */
- fz_printf(out, "\033*t%dR", xres);
- pcl->page_count++;
-}
-
-void
-fz_output_pcl(fz_output *out, const fz_pixmap *pixmap, fz_pcl_options *pcl)
-{
- //unsigned char *sp;
- //int y, x, sn, dn, ss;
- fz_context *ctx;
-
- if (!out || !pixmap)
- return;
-
- ctx = out->ctx;
-
- if (pixmap->n != 1 && pixmap->n != 2 && pixmap->n != 4)
- fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be grayscale or rgb to write as pcl");
-
- pcl_header(out, pcl, 1, pixmap->xres);
-
-#if 0
- sn = pixmap->n;
- dn = pixmap->n;
- if (dn == 2 || dn == 4)
- dn--;
-
- /* Now output the actual bitmap, using a packbits like compression */
- sp = pixmap->samples;
- ss = pixmap->w * sn;
- y = 0;
- while (y < pixmap->h)
- {
- int yrep;
-
- assert(sp == pixmap->samples + y * ss);
-
- /* Count the number of times this line is repeated */
- for (yrep = 1; yrep < 256 && y+yrep < pixmap->h; yrep++)
- {
- if (memcmp(sp, sp + yrep * ss, ss) != 0)
- break;
- }
- fz_write_byte(out, yrep-1);
-
- /* Encode the line */
- x = 0;
- while (x < pixmap->w)
- {
- int d;
-
- assert(sp == pixmap->samples + y * ss + x * sn);
-
- /* How far do we have to look to find a repeated value? */
- for (d = 1; d < 128 && x+d < pixmap->w; d++)
- {
- if (memcmp(sp + (d-1)*sn, sp + d*sn, sn) == 0)
- break;
- }
- if (d == 1)
- {
- int xrep;
-
- /* We immediately have a repeat (or we've hit
- * the end of the line). Count the number of
- * times this value is repeated. */
- for (xrep = 1; xrep < 128 && x+xrep < pixmap->w; xrep++)
- {
- if (memcmp(sp, sp + xrep*sn, sn) != 0)
- break;
- }
- fz_write_byte(out, xrep-1);
- fz_write(out, sp, dn);
- sp += sn*xrep;
- x += xrep;
- }
- else
- {
- fz_write_byte(out, 257-d);
- x += d;
- while (d > 0)
- {
- fz_write(out, sp, dn);
- sp += sn;
- d--;
- }
- }
- }
-
- /* Move to the next line */
- sp += ss*(yrep-1);
- y += yrep;
- }
-#endif
-}
-
-/*
- * Mode 2 Row compression routine for the HP DeskJet & LaserJet IIp.
- * Compresses data from row up to end_row, storing the result
- * starting at compressed. Returns the number of bytes stored.
- * Runs of K<=127 literal bytes are encoded as K-1 followed by
- * the bytes; runs of 2<=K<=127 identical bytes are encoded as
- * 257-K followed by the byte.
- * In the worst case, the result is N+(N/127)+1 bytes long,
- * where N is the original byte count (end_row - row).
- */
-int
-mode2compress(unsigned char *out, unsigned char *in, int in_len)
-{
- int x;
- int out_len = 0;
- int run;
-
- for (x = 0; x < in_len; x += run)
- {
- /* How far do we have to look to find a value that isn't repeated? */
- for (run = 1; run < 127 && x+run < in_len; run++)
- if (in[0] != in[run])
- break;
- if (run > 1)
- {
- /* We have a run of matching bytes */
- out[out_len++] = 257-run;
- out[out_len++] = in[0];
- }
- else
- {
- int i;
-
- /* How many literals do we need to copy? */
- for (run = 1; run < 127 && x+run < in_len; run++)
- if (in[run] == in[run+1])
- break;
- out[out_len++] = run-1;
- for (i = 0; i < run; i++)
- out[out_len++] = in[i];
- }
- in += run;
- }
- return out_len;
-}
-
-/*
- * Mode 3 compression routine for the HP LaserJet III family.
- * Compresses bytecount bytes starting at current, storing the result
- * in compressed, comparing against and updating previous.
- * Returns the number of bytes stored. In the worst case,
- * the number of bytes is bytecount+(bytecount/8)+1.
- */
-int
-mode3compress(unsigned char *out, const unsigned char *in, unsigned char *prev, int in_len)
-{
- unsigned char *compressed = out;
- const unsigned char *cur = in;
- const unsigned char *end = in + in_len;
-
- while (cur < end) { /* Detect a maximum run of unchanged bytes. */
- const unsigned char *run = cur;
- const unsigned char *diff;
- const unsigned char *stop;
- int offset, cbyte;
-
- while (cur < end && *cur == *prev) {
- cur++, prev++;
- }
- if (cur == end)
- break; /* rest of row is unchanged */
- /* Detect a run of up to 8 changed bytes. */
- /* We know that *cur != *prev. */
- diff = cur;
- stop = (end - cur > 8 ? cur + 8 : end);
- do
- {
- *prev++ = *cur++;
- }
- while (cur < stop && *cur != *prev);
- /* Now [run..diff) are unchanged, and */
- /* [diff..cur) are changed. */
- /* Generate the command byte(s). */
- offset = diff - run;
- cbyte = (cur - diff - 1) << 5;
- if (offset < 31)
- *out++ = cbyte + offset;
- else {
- *out++ = cbyte + 31;
- offset -= 31;
- while (offset >= 255)
- *out++ = 255, offset -= 255;
- *out++ = offset;
- }
- /* Copy the changed data. */
- while (diff < cur)
- *out++ = *diff++;
- }
- return out - compressed;
-}
-
-void wind(void)
-{}
-
-void
-fz_output_pcl_bitmap(fz_output *out, const fz_bitmap *bitmap, fz_pcl_options *pcl)
-{
- unsigned char *data, *out_data;
- int y, ss, rmask, line_size;
- fz_context *ctx;
- int num_blank_lines;
- int compression = -1;
- unsigned char *prev_row = NULL;
- unsigned char *out_row_mode_2 = NULL;
- unsigned char *out_row_mode_3 = NULL;
- int out_count;
- int max_mode_2_size;
- int max_mode_3_size;
-
- if (!out || !bitmap)
- return;
-
- ctx = out->ctx;
-
- if (pcl->features & HACK__IS_A_OCE9050)
- {
- /* Enter HPGL/2 mode, begin plot, Initialise (start plot), Enter PCL mode */
- fz_puts(out, "\033%1BBPIN;\033%1A");
- }
-
- pcl_header(out, pcl, 1, bitmap->xres);
-
- fz_var(prev_row);
- fz_var(out_row_mode_2);
- fz_var(out_row_mode_3);
-
- fz_try(ctx)
- {
- num_blank_lines = 0;
- rmask = ~0 << (-bitmap->w & 7);
- line_size = (bitmap->w + 7)/8;
- max_mode_2_size = line_size + (line_size/127) + 1;
- max_mode_3_size = line_size + (line_size/8) + 1;
- prev_row = fz_calloc(ctx, line_size, sizeof(unsigned char));
- out_row_mode_2 = fz_calloc(ctx, max_mode_2_size, sizeof(unsigned char));
- out_row_mode_3 = fz_calloc(ctx, max_mode_3_size, sizeof(unsigned char));
-
- /* Transfer raster graphics. */
- data = bitmap->samples;
- ss = bitmap->stride;
- for (y = 0; y < bitmap->h; y++, data += ss)
- {
- unsigned char *end_data = data + line_size;
-
- if ((end_data[-1] & rmask) == 0)
- {
- end_data--;
- while (end_data > data && end_data[-1] == 0)
- end_data--;
- }
- if (end_data == data)
- {
- /* Blank line */
- num_blank_lines++;
- continue;
- }
- wind();
-
- /* We've reached a non-blank line. */
- /* Put out a spacing command if necessary. */
- if (num_blank_lines == y) {
- /* We're at the top of a page. */
- if (pcl->features & PCL_ANY_SPACING)
- {
- if (num_blank_lines > 0)
- fz_printf(out, "\033*p+%dY", num_blank_lines * bitmap->yres);
- /* Start raster graphics. */
- fz_puts(out, "\033*r1A");
- }
- else if (pcl->features & PCL_MODE_3_COMPRESSION)
- {
- /* Start raster graphics. */
- fz_puts(out, "\033*r1A");
- for (; num_blank_lines; num_blank_lines--)
- fz_puts(out, "\033*b0W");
- }
- else
- {
- /* Start raster graphics. */
- fz_puts(out, "\033*r1A");
- for (; num_blank_lines; num_blank_lines--)
- fz_puts(out, "\033*bW");
- }
- }
-
- /* Skip blank lines if any */
- else if (num_blank_lines != 0)
- {
- /* Moving down from current position causes head
- * motion on the DeskJet, so if the number of lines
- * is small, we're better off printing blanks.
- *
- * For Canon LBP4i and some others, <ESC>*b<n>Y
- * doesn't properly clear the seed row if we are in
- * compression mode 3.
- */
- if ((num_blank_lines < MIN_SKIP_LINES && compression != 3) ||
- !(pcl->features & PCL_ANY_SPACING))
- {
- int mode_3ns = ((pcl->features & PCL_MODE_3_COMPRESSION) && !(pcl->features & PCL_ANY_SPACING));
- if (mode_3ns && compression != 2)
- {
- /* Switch to mode 2 */
- fz_puts(out, from3to2);
- compression = 2;
- }
- if (pcl->features & PCL_MODE_3_COMPRESSION)
- {
- /* Must clear the seed row. */
- fz_puts(out, "\033*b1Y");
- num_blank_lines--;
- }
- if (mode_3ns)
- {
- for (; num_blank_lines; num_blank_lines--)
- fz_puts(out, "\033*b0W");
- }
- else
- {
- for (; num_blank_lines; num_blank_lines--)
- fz_puts(out, "\033*bW");
- }
- }
- else if (pcl->features & PCL3_SPACING)
- fz_printf(out, "\033*p+%dY", num_blank_lines * bitmap->yres);
- else
- fz_printf(out, "\033*b%dY", num_blank_lines);
- /* Clear the seed row (only matters for mode 3 compression). */
- memset(prev_row, 0, line_size);
- }
- num_blank_lines = 0;
-
- /* Choose the best compression mode for this particular line. */
- if (pcl->features & PCL_MODE_3_COMPRESSION)
- {
- /* Compression modes 2 and 3 are both available. Try
- * both and see which produces the least output data.
- */
- int count3 = mode3compress(out_row_mode_3, data, prev_row, line_size);
- int count2 = mode2compress(out_row_mode_2, data, line_size);
- int penalty3 = (compression == 3 ? 0 : penalty_from2to3);
- int penalty2 = (compression == 2 ? 0 : penalty_from3to2);
-
- if (count3 + penalty3 < count2 + penalty2)
- {
- if (compression != 3)
- fz_puts(out, from2to3);
- compression = 3;
- out_data = (unsigned char *)out_row_mode_3;
- out_count = count3;
- }
- else
- {
- if (compression != 2)
- fz_puts(out, from3to2);
- compression = 2;
- out_data = (unsigned char *)out_row_mode_2;
- out_count = count2;
- }
- }
- else if (pcl->features & PCL_MODE_2_COMPRESSION)
- {
- out_data = out_row_mode_2;
- out_count = mode2compress(out_row_mode_2, data, line_size);
- }
- else
- {
- out_data = data;
- out_count = line_size;
- }
-
- /* Transfer the data */
- fz_printf(out, "\033*b%dW", out_count);
- fz_write(out, out_data, out_count);
- }
-
- /* end raster graphics and eject page */
- fz_puts(out, "\033*rB\f");
-
- if (pcl->features & HACK__IS_A_OCE9050)
- {
- /* Pen up, pen select, advance full page, reset */
- fz_puts(out, "\033%1BPUSP0PG;\033E");
- }
- }
- fz_always(ctx)
- {
- fz_free(ctx, prev_row);
- fz_free(ctx, out_row_mode_2);
- fz_free(ctx, out_row_mode_3);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
-}
-
-void
-fz_write_pcl(fz_context *ctx, fz_pixmap *pixmap, char *filename, int append, fz_pcl_options *pcl)
-{
- FILE *fp;
- fz_output *out = NULL;
-
- fp = fopen(filename, append ? "ab" : "wb");
- if (!fp)
- {
- fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open file '%s': %s", filename, strerror(errno));
- }
-
- fz_var(out);
-
- fz_try(ctx)
- {
- out = fz_new_output_with_file(ctx, fp);
- fz_output_pcl(out, pixmap, pcl);
- }
- fz_always(ctx)
- {
- fz_close_output(out);
- fclose(fp);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
-}
-
-void
-fz_write_pcl_bitmap(fz_context *ctx, fz_bitmap *bitmap, char *filename, int append, fz_pcl_options *pcl)
-{
- FILE *fp;
- fz_output *out = NULL;
-
- fp = fopen(filename, append ? "ab" : "wb");
- if (!fp)
- {
- fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open file '%s': %s", filename, strerror(errno));
- }
-
- fz_var(out);
-
- fz_try(ctx)
- {
- out = fz_new_output_with_file(ctx, fp);
- fz_output_pcl_bitmap(out, bitmap, pcl);
- }
- fz_always(ctx)
- {
- fz_close_output(out);
- fclose(fp);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
-}
diff --git a/fitz/res_pixmap.c b/fitz/res_pixmap.c
deleted file mode 100644
index 7391c17e..00000000
--- a/fitz/res_pixmap.c
+++ /dev/null
@@ -1,1062 +0,0 @@
-#include "mupdf/fitz.h"
-
-fz_pixmap *
-fz_keep_pixmap(fz_context *ctx, fz_pixmap *pix)
-{
- return (fz_pixmap *)fz_keep_storable(ctx, &pix->storable);
-}
-
-void
-fz_drop_pixmap(fz_context *ctx, fz_pixmap *pix)
-{
- fz_drop_storable(ctx, &pix->storable);
-}
-
-void
-fz_free_pixmap_imp(fz_context *ctx, fz_storable *pix_)
-{
- fz_pixmap *pix = (fz_pixmap *)pix_;
-
- if (pix->colorspace)
- fz_drop_colorspace(ctx, pix->colorspace);
- if (pix->free_samples)
- fz_free(ctx, pix->samples);
- fz_free(ctx, pix);
-}
-
-fz_pixmap *
-fz_new_pixmap_with_data(fz_context *ctx, fz_colorspace *colorspace, int w, int h, unsigned char *samples)
-{
- fz_pixmap *pix;
-
- if (w < 0 || h < 0)
- fz_throw(ctx, FZ_ERROR_GENERIC, "Illegal dimensions for pixmap %d %d", w, h);
-
- pix = fz_malloc_struct(ctx, fz_pixmap);
- FZ_INIT_STORABLE(pix, 1, fz_free_pixmap_imp);
- pix->x = 0;
- pix->y = 0;
- pix->w = w;
- pix->h = h;
- pix->interpolate = 1;
- pix->xres = 96;
- pix->yres = 96;
- pix->colorspace = NULL;
- pix->n = 1;
-
- if (colorspace)
- {
- pix->colorspace = fz_keep_colorspace(ctx, colorspace);
- pix->n = 1 + colorspace->n;
- }
-
- pix->samples = samples;
- if (samples)
- {
- pix->free_samples = 0;
- }
- else
- {
- fz_try(ctx)
- {
- if (pix->w + pix->n - 1 > INT_MAX / pix->n)
- fz_throw(ctx, FZ_ERROR_GENERIC, "overly wide image");
- pix->samples = fz_malloc_array(ctx, pix->h, pix->w * pix->n);
- }
- fz_catch(ctx)
- {
- if (colorspace)
- fz_drop_colorspace(ctx, colorspace);
- fz_free(ctx, pix);
- fz_rethrow(ctx);
- }
- pix->free_samples = 1;
- }
-
- return pix;
-}
-
-fz_pixmap *
-fz_new_pixmap(fz_context *ctx, fz_colorspace *colorspace, int w, int h)
-{
- return fz_new_pixmap_with_data(ctx, colorspace, w, h, NULL);
-}
-
-fz_pixmap *
-fz_new_pixmap_with_bbox(fz_context *ctx, fz_colorspace *colorspace, const fz_irect *r)
-{
- fz_pixmap *pixmap;
- pixmap = fz_new_pixmap(ctx, colorspace, r->x1 - r->x0, r->y1 - r->y0);
- pixmap->x = r->x0;
- pixmap->y = r->y0;
- return pixmap;
-}
-
-fz_pixmap *
-fz_new_pixmap_with_bbox_and_data(fz_context *ctx, fz_colorspace *colorspace, const fz_irect *r, unsigned char *samples)
-{
- fz_pixmap *pixmap = fz_new_pixmap_with_data(ctx, colorspace, r->x1 - r->x0, r->y1 - r->y0, samples);
- pixmap->x = r->x0;
- pixmap->y = r->y0;
- return pixmap;
-}
-
-fz_irect *
-fz_pixmap_bbox(fz_context *ctx, fz_pixmap *pix, fz_irect *bbox)
-{
- bbox->x0 = pix->x;
- bbox->y0 = pix->y;
- bbox->x1 = pix->x + pix->w;
- bbox->y1 = pix->y + pix->h;
- return bbox;
-}
-
-fz_irect *
-fz_pixmap_bbox_no_ctx(fz_pixmap *pix, fz_irect *bbox)
-{
- bbox->x0 = pix->x;
- bbox->y0 = pix->y;
- bbox->x1 = pix->x + pix->w;
- bbox->y1 = pix->y + pix->h;
- 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)
-{
- memset(pix->samples, 0, (unsigned int)(pix->w * pix->h * pix->n));
-}
-
-void
-fz_clear_pixmap_with_value(fz_context *ctx, fz_pixmap *pix, int value)
-{
- if (value == 255)
- {
- memset(pix->samples, 255, (unsigned int)(pix->w * pix->h * pix->n));
- }
- else
- {
- int k, x, y;
- unsigned char *s = pix->samples;
- for (y = 0; y < pix->h; y++)
- {
- for (x = 0; x < pix->w; x++)
- {
- for (k = 0; k < pix->n - 1; k++)
- *s++ = value;
- *s++ = 255;
- }
- }
- }
-}
-
-void
-fz_copy_pixmap_rect(fz_context *ctx, fz_pixmap *dest, fz_pixmap *src, const fz_irect *b)
-{
- const unsigned char *srcp;
- unsigned char *destp;
- int x, y, w, destspan, srcspan;
- fz_irect local_b, bb;
-
- local_b = *b;
- fz_intersect_irect(&local_b, fz_pixmap_bbox(ctx, dest, &bb));
- fz_intersect_irect(&local_b, fz_pixmap_bbox(ctx, src, &bb));
- w = local_b.x1 - local_b.x0;
- y = local_b.y1 - local_b.y0;
- if (w <= 0 || y <= 0)
- return;
-
- srcspan = src->w * src->n;
- srcp = src->samples + (unsigned int)(srcspan * (local_b.y0 - src->y) + src->n * (local_b.x0 - src->x));
- destspan = dest->w * dest->n;
- destp = dest->samples + (unsigned int)(destspan * (local_b.y0 - dest->y) + dest->n * (local_b.x0 - dest->x));
-
- if (src->n == dest->n)
- {
- w *= src->n;
- do
- {
- memcpy(destp, srcp, w);
- srcp += srcspan;
- destp += destspan;
- }
- while (--y);
- }
- else if (src->n == 2 && dest->n == 4)
- {
- /* Copy, and convert from grey+alpha to rgb+alpha */
- srcspan -= w*2;
- destspan -= w*4;
- do
- {
- for (x = w; x > 0; x--)
- {
- unsigned char v = *srcp++;
- unsigned char a = *srcp++;
- *destp++ = v;
- *destp++ = v;
- *destp++ = v;
- *destp++ = a;
- }
- srcp += srcspan;
- destp += destspan;
- }
- while (--y);
- }
- else if (src->n == 4 && dest->n == 2)
- {
- /* Copy, and convert from rgb+alpha to grey+alpha */
- srcspan -= w*4;
- destspan -= w*2;
- do
- {
- for (x = w; x > 0; x--)
- {
- int v;
- v = *srcp++;
- v += *srcp++;
- v += *srcp++;
- *destp++ = (unsigned char)((v+1)/3);
- *destp++ = *srcp++;
- }
- srcp += srcspan;
- destp += destspan;
- }
- while (--y);
- }
- else
- {
- /* FIXME: Crap conversion */
- int z;
- int sn = src->n-1;
- int dn = dest->n-1;
-
- srcspan -= w*src->n;
- destspan -= w*dest->n;
- do
- {
- for (x = w; x > 0; x--)
- {
- int v = 0;
- for (z = sn; z > 0; z--)
- v += *srcp++;
- v = (v * dn + (sn>>1)) / sn;
- for (z = dn; z > 0; z--)
- *destp++ = (unsigned char)v;
- *destp++ = *srcp++;
- }
- srcp += srcspan;
- destp += destspan;
- }
- while (--y);
- }
-}
-
-void
-fz_clear_pixmap_rect_with_value(fz_context *ctx, fz_pixmap *dest, int value, const fz_irect *b)
-{
- unsigned char *destp;
- int x, y, w, k, destspan;
- fz_irect bb;
- fz_irect local_b = *b;
-
- fz_intersect_irect(&local_b, fz_pixmap_bbox(ctx, dest, &bb));
- w = local_b.x1 - local_b.x0;
- y = local_b.y1 - local_b.y0;
- if (w <= 0 || y <= 0)
- return;
-
- destspan = dest->w * dest->n;
- destp = dest->samples + (unsigned int)(destspan * (local_b.y0 - dest->y) + dest->n * (local_b.x0 - dest->x));
- if (value == 255)
- do
- {
- memset(destp, 255, (unsigned int)(w * dest->n));
- destp += destspan;
- }
- while (--y);
- else
- do
- {
- unsigned char *s = destp;
- for (x = 0; x < w; x++)
- {
- for (k = 0; k < dest->n - 1; k++)
- *s++ = value;
- *s++ = 255;
- }
- destp += destspan;
- }
- while (--y);
-}
-
-void
-fz_premultiply_pixmap(fz_context *ctx, fz_pixmap *pix)
-{
- unsigned char *s = pix->samples;
- unsigned char a;
- int k, x, y;
-
- for (y = 0; y < pix->h; y++)
- {
- for (x = 0; x < pix->w; x++)
- {
- a = s[pix->n - 1];
- for (k = 0; k < pix->n - 1; k++)
- s[k] = fz_mul255(s[k], a);
- s += pix->n;
- }
- }
-}
-
-void
-fz_unmultiply_pixmap(fz_context *ctx, fz_pixmap *pix)
-{
- unsigned char *s = pix->samples;
- int a, inva;
- int k, x, y;
-
- for (y = 0; y < pix->h; y++)
- {
- for (x = 0; x < pix->w; x++)
- {
- a = s[pix->n - 1];
- inva = a ? 255 * 256 / a : 0;
- for (k = 0; k < pix->n - 1; k++)
- s[k] = (s[k] * inva) >> 8;
- s += pix->n;
- }
- }
-}
-
-fz_pixmap *
-fz_alpha_from_gray(fz_context *ctx, fz_pixmap *gray, int luminosity)
-{
- fz_pixmap *alpha;
- unsigned char *sp, *dp;
- int len;
- fz_irect bbox;
-
- assert(gray->n == 2);
-
- alpha = fz_new_pixmap_with_bbox(ctx, NULL, fz_pixmap_bbox(ctx, gray, &bbox));
- dp = alpha->samples;
- sp = gray->samples;
- if (!luminosity)
- sp ++;
-
- len = gray->w * gray->h;
- while (len--)
- {
- *dp++ = sp[0];
- sp += 2;
- }
-
- return alpha;
-}
-
-void
-fz_invert_pixmap(fz_context *ctx, fz_pixmap *pix)
-{
- unsigned char *s = pix->samples;
- int k, x, y;
-
- for (y = 0; y < pix->h; y++)
- {
- for (x = 0; x < pix->w; x++)
- {
- for (k = 0; k < pix->n - 1; k++)
- s[k] = 255 - s[k];
- s += pix->n;
- }
- }
-}
-
-void fz_invert_pixmap_rect(fz_pixmap *image, const fz_irect *rect)
-{
- unsigned char *p;
- int x, y, n;
-
- int x0 = fz_clampi(rect->x0 - image->x, 0, image->w - 1);
- int x1 = fz_clampi(rect->x1 - image->x, 0, image->w - 1);
- int y0 = fz_clampi(rect->y0 - image->y, 0, image->h - 1);
- int y1 = fz_clampi(rect->y1 - image->y, 0, image->h - 1);
-
- for (y = y0; y < y1; y++)
- {
- p = image->samples + (unsigned int)((y * image->w + x0) * image->n);
- for (x = x0; x < x1; x++)
- {
- for (n = image->n; n > 1; n--, p++)
- *p = 255 - *p;
- p++;
- }
- }
-}
-
-void
-fz_gamma_pixmap(fz_context *ctx, fz_pixmap *pix, float gamma)
-{
- unsigned char gamma_map[256];
- unsigned char *s = pix->samples;
- int k, x, y;
-
- for (k = 0; k < 256; k++)
- gamma_map[k] = pow(k / 255.0f, gamma) * 255;
-
- for (y = 0; y < pix->h; y++)
- {
- for (x = 0; x < pix->w; x++)
- {
- for (k = 0; k < pix->n - 1; k++)
- s[k] = gamma_map[s[k]];
- s += pix->n;
- }
- }
-}
-
-/*
- * Write pixmap to PNM file (without alpha channel)
- */
-
-void
-fz_write_pnm(fz_context *ctx, fz_pixmap *pixmap, char *filename)
-{
- FILE *fp;
- unsigned char *p;
- int len;
-
- if (pixmap->n != 1 && pixmap->n != 2 && pixmap->n != 4)
- fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be grayscale or rgb to write as pnm");
-
- fp = fopen(filename, "wb");
- if (!fp)
- fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open file '%s': %s", filename, strerror(errno));
-
- if (pixmap->n == 1 || pixmap->n == 2)
- fprintf(fp, "P5\n");
- if (pixmap->n == 4)
- fprintf(fp, "P6\n");
- fprintf(fp, "%d %d\n", pixmap->w, pixmap->h);
- fprintf(fp, "255\n");
-
- len = pixmap->w * pixmap->h;
- p = pixmap->samples;
-
- switch (pixmap->n)
- {
- case 1:
- fwrite(p, 1, len, fp);
- break;
- case 2:
- while (len--)
- {
- putc(p[0], fp);
- p += 2;
- }
- break;
- case 4:
- while (len--)
- {
- putc(p[0], fp);
- putc(p[1], fp);
- putc(p[2], fp);
- p += 4;
- }
- }
-
- fclose(fp);
-}
-
-/*
- * Write pixmap to PAM file (with or without alpha channel)
- */
-
-void
-fz_write_pam(fz_context *ctx, fz_pixmap *pixmap, char *filename, int savealpha)
-{
- unsigned char *sp;
- int y, w, k;
- FILE *fp;
-
- int sn = pixmap->n;
- int dn = pixmap->n;
- if (!savealpha && dn > 1)
- dn--;
-
- fp = fopen(filename, "wb");
- if (!fp)
- fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open file '%s': %s", filename, strerror(errno));
-
- fprintf(fp, "P7\n");
- fprintf(fp, "WIDTH %d\n", pixmap->w);
- fprintf(fp, "HEIGHT %d\n", pixmap->h);
- fprintf(fp, "DEPTH %d\n", dn);
- fprintf(fp, "MAXVAL 255\n");
- if (pixmap->colorspace)
- fprintf(fp, "# COLORSPACE %s\n", pixmap->colorspace->name);
- switch (dn)
- {
- case 1: fprintf(fp, "TUPLTYPE GRAYSCALE\n"); break;
- case 2: if (sn == 2) fprintf(fp, "TUPLTYPE GRAYSCALE_ALPHA\n"); break;
- case 3: if (sn == 4) fprintf(fp, "TUPLTYPE RGB\n"); break;
- case 4: if (sn == 4) fprintf(fp, "TUPLTYPE RGB_ALPHA\n"); break;
- }
- fprintf(fp, "ENDHDR\n");
-
- sp = pixmap->samples;
- for (y = 0; y < pixmap->h; y++)
- {
- w = pixmap->w;
- while (w--)
- {
- for (k = 0; k < dn; k++)
- putc(sp[k], fp);
- sp += sn;
- }
- }
-
- fclose(fp);
-}
-
-/*
- * Write pixmap to PNG file (with or without alpha channel)
- */
-
-#include <zlib.h>
-
-static inline void big32(unsigned char *buf, unsigned int v)
-{
- buf[0] = (v >> 24) & 0xff;
- buf[1] = (v >> 16) & 0xff;
- buf[2] = (v >> 8) & 0xff;
- buf[3] = (v) & 0xff;
-}
-
-static void putchunk(char *tag, unsigned char *data, int size, fz_output *out)
-{
- unsigned int sum;
- fz_write_int32be(out, size);
- fz_write(out, tag, 4);
- fz_write(out, data, size);
- sum = crc32(0, NULL, 0);
- sum = crc32(sum, (unsigned char*)tag, 4);
- sum = crc32(sum, data, size);
- fz_write_int32be(out, sum);
-}
-
-void
-fz_write_png(fz_context *ctx, fz_pixmap *pixmap, char *filename, int savealpha)
-{
- FILE *fp = fopen(filename, "wb");
- fz_output *out = NULL;
-
- if (!fp)
- {
- fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open file '%s': %s", filename, strerror(errno));
- }
-
- fz_var(out);
-
- fz_try(ctx)
- {
- out = fz_new_output_with_file(ctx, fp);
- fz_output_png(out, pixmap, savealpha);
- }
- fz_always(ctx)
- {
- fz_close_output(out);
- fclose(fp);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
-}
-
-void
-fz_output_png(fz_output *out, const fz_pixmap *pixmap, int savealpha)
-{
- static const unsigned char pngsig[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
- unsigned char head[13];
- unsigned char *udata = NULL;
- unsigned char *cdata = NULL;
- unsigned char *sp, *dp;
- uLong usize, csize;
- int y, x, k, sn, dn;
- int color;
- int err;
- fz_context *ctx;
-
- if (!out || !pixmap)
- return;
-
- ctx = out->ctx;
-
- fz_var(udata);
- fz_var(cdata);
-
- if (pixmap->n != 1 && pixmap->n != 2 && pixmap->n != 4)
- fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be grayscale or rgb to write as png");
-
- sn = pixmap->n;
- dn = pixmap->n;
- if (!savealpha && dn > 1)
- dn--;
-
- switch (dn)
- {
- default:
- case 1: color = 0; break;
- case 2: color = 4; break;
- case 3: color = 2; break;
- case 4: color = 6; break;
- }
-
- usize = (pixmap->w * dn + 1) * pixmap->h;
- csize = compressBound(usize);
- fz_try(ctx)
- {
- udata = fz_malloc(ctx, usize);
- cdata = fz_malloc(ctx, csize);
- }
- fz_catch(ctx)
- {
- fz_free(ctx, udata);
- fz_rethrow(ctx);
- }
-
- sp = pixmap->samples;
- dp = udata;
- for (y = 0; y < pixmap->h; y++)
- {
- *dp++ = 1; /* sub prediction filter */
- for (x = 0; x < pixmap->w; x++)
- {
- for (k = 0; k < dn; k++)
- {
- if (x == 0)
- dp[k] = sp[k];
- else
- dp[k] = sp[k] - sp[k-sn];
- }
- sp += sn;
- dp += dn;
- }
- }
-
- err = compress(cdata, &csize, udata, usize);
- if (err != Z_OK)
- {
- fz_free(ctx, udata);
- fz_free(ctx, cdata);
- fz_throw(ctx, FZ_ERROR_GENERIC, "cannot compress image data");
- }
-
- big32(head+0, pixmap->w);
- big32(head+4, pixmap->h);
- head[8] = 8; /* depth */
- head[9] = color;
- head[10] = 0; /* compression */
- head[11] = 0; /* filter */
- head[12] = 0; /* interlace */
-
- fz_write(out, pngsig, 8);
- putchunk("IHDR", head, 13, out);
- putchunk("IDAT", cdata, csize, out);
- putchunk("IEND", head, 0, out);
-
- fz_free(ctx, udata);
- fz_free(ctx, cdata);
-}
-
-fz_buffer *
-fz_image_as_png(fz_context *ctx, fz_image *image, int w, int h)
-{
- fz_pixmap *pix = fz_image_get_pixmap(ctx, image, image->w, image->h);
- fz_buffer *buf = NULL;
- fz_output *out;
-
- fz_var(buf);
- fz_var(out);
-
- fz_try(ctx)
- {
- if (pix->colorspace != fz_device_gray(ctx) || pix->colorspace != fz_device_rgb(ctx))
- {
- fz_pixmap *pix2 = fz_new_pixmap(ctx, fz_device_rgb(ctx), pix->w, pix->h);
- fz_convert_pixmap(ctx, pix2, pix);
- fz_drop_pixmap(ctx, pix);
- pix = pix2;
- }
- buf = fz_new_buffer(ctx, 1024);
- out = fz_new_output_with_buffer(ctx, buf);
- fz_output_png(out, pix, 0);
- }
- fz_always(ctx)
- {
- fz_close_output(out);
- fz_drop_pixmap(ctx, pix);
- }
- fz_catch(ctx)
- {
- fz_drop_buffer(ctx, buf);
- fz_rethrow(ctx);
- }
- return buf;
-}
-
-unsigned int
-fz_pixmap_size(fz_context *ctx, fz_pixmap * pix)
-{
- if (pix == NULL)
- return 0;
- return sizeof(*pix) + pix->n * pix->w * pix->h;
-}
-
-#ifdef ARCH_ARM
-static void
-fz_subsample_pixmap_ARM(unsigned char *ptr, int w, int h, int f, int factor,
- int n, int fwd, int back, int back2, int fwd2,
- int divX, int back4, int fwd4, int fwd3,
- int divY, int back5, int divXY)
-__attribute__((naked));
-
-static void
-fz_subsample_pixmap_ARM(unsigned char *ptr, int w, int h, int f, int factor,
- int n, int fwd, int back, int back2, int fwd2,
- int divX, int back4, int fwd4, int fwd3,
- int divY, int back5, int divXY)
-{
- asm volatile(
- ENTER_ARM
- "stmfd r13!,{r1,r4-r11,r14} \n"
- "@STACK:r1,<9>,factor,n,fwd,back,back2,fwd2,divX,back4,fwd4,fwd3,divY,back5,divXY\n"
- "@ r0 = src = ptr \n"
- "@ r1 = w \n"
- "@ r2 = h \n"
- "@ r3 = f \n"
- "mov r9, r0 @ r9 = dst = ptr \n"
- "ldr r6, [r13,#4*12] @ r6 = fwd \n"
- "ldr r7, [r13,#4*13] @ r7 = back \n"
- "subs r2, r2, r3 @ r2 = h -= f \n"
- "blt 11f @ Skip if less than a full row \n"
- "1: @ for (y = h; y > 0; y--) { \n"
- "ldr r1, [r13] @ r1 = w \n"
- "subs r1, r1, r3 @ r1 = w -= f \n"
- "blt 6f @ Skip if less than a full col \n"
- "ldr r4, [r13,#4*10] @ r4 = factor \n"
- "ldr r8, [r13,#4*14] @ r8 = back2 \n"
- "ldr r12,[r13,#4*15] @ r12= fwd2 \n"
- "2: @ for (x = w; x > 0; x--) { \n"
- "ldr r5, [r13,#4*11] @ for (nn = n; nn > 0; n--) { \n"
- "3: @ \n"
- "mov r14,#0 @ r14= v = 0 \n"
- "sub r5, r5, r3, LSL #8 @ for (xx = f; xx > 0; x--) { \n"
- "4: @ \n"
- "add r5, r5, r3, LSL #16 @ for (yy = f; yy > 0; y--) { \n"
- "5: @ \n"
- "ldrb r11,[r0], r6 @ r11= *src src += fwd \n"
- "subs r5, r5, #1<<16 @ xx-- \n"
- "add r14,r14,r11 @ v += r11 \n"
- "bgt 5b @ } \n"
- "sub r0, r0, r7 @ src -= back \n"
- "adds r5, r5, #1<<8 @ yy-- \n"
- "blt 4b @ } \n"
- "mov r14,r14,LSR r4 @ r14 = v >>= factor \n"
- "strb r14,[r9], #1 @ *d++ = r14 \n"
- "sub r0, r0, r8 @ s -= back2 \n"
- "subs r5, r5, #1 @ n-- \n"
- "bgt 3b @ } \n"
- "add r0, r0, r12 @ s += fwd2 \n"
- "subs r1, r1, r3 @ x -= f \n"
- "bge 2b @ } \n"
- "6: @ Less than a full column left \n"
- "adds r1, r1, r3 @ x += f \n"
- "beq 11f @ if (x == 0) next row \n"
- "@ r0 = src \n"
- "@ r1 = x \n"
- "@ r2 = y \n"
- "@ r3 = f \n"
- "@ r4 = factor \n"
- "@ r6 = fwd \n"
- "@ r7 = back \n"
- "@STACK:r1,<9>,factor,n,fwd,back,back2,fwd2,divX,back4,fwd4,fwd3,divY,back5,divXY\n"
- "ldr r5, [r13,#4*11] @ for (nn = n; nn > 0; n--) { \n"
- "ldr r4, [r13,#4*16] @ r4 = divX \n"
- "ldr r8, [r13,#4*17] @ r8 = back4 \n"
- "ldr r12,[r13,#4*18] @ r12= fwd4 \n"
- "8: @ \n"
- "mov r14,#0 @ r14= v = 0 \n"
- "sub r5, r5, r1, LSL #8 @ for (xx = x; xx > 0; x--) { \n"
- "9: @ \n"
- "add r5, r5, r3, LSL #16 @ for (yy = f; yy > 0; y--) { \n"
- "10: @ \n"
- "ldrb r11,[r0], r6 @ r11= *src src += fwd \n"
- "subs r5, r5, #1<<16 @ xx-- \n"
- "add r14,r14,r11 @ v += r11 \n"
- "bgt 10b @ } \n"
- "sub r0, r0, r7 @ src -= back \n"
- "adds r5, r5, #1<<8 @ yy-- \n"
- "blt 9b @ } \n"
- "mul r14,r4, r14 @ r14= v *= divX \n"
- "mov r14,r14,LSR #16 @ r14= v >>= 16 \n"
- "strb r14,[r9], #1 @ *d++ = r14 \n"
- "sub r0, r0, r8 @ s -= back4 \n"
- "subs r5, r5, #1 @ n-- \n"
- "bgt 8b @ } \n"
- "add r0, r0, r12 @ s += fwd4 \n"
- "11: @ \n"
- "ldr r14,[r13,#4*19] @ r14 = fwd3 \n"
- "subs r2, r2, r3 @ h -= f \n"
- "add r0, r0, r14 @ s += fwd3 \n"
- "bge 1b @ } \n"
- "adds r2, r2, r3 @ h += f \n"
- "beq 21f @ if no stray row, end \n"
- "@ So doing one last (partial) row \n"
- "@STACK:r1,<9>,factor,n,fwd,back,back2,fwd2,divX,back4,fwd4,fwd3,divY,back5,divXY\n"
- "@ r0 = src = ptr \n"
- "@ r1 = w \n"
- "@ r2 = h \n"
- "@ r3 = f \n"
- "@ r4 = factor \n"
- "@ r5 = n \n"
- "@ r6 = fwd \n"
- "12: @ for (y = h; y > 0; y--) { \n"
- "ldr r1, [r13] @ r1 = w \n"
- "ldr r7, [r13,#4*21] @ r7 = back5 \n"
- "ldr r8, [r13,#4*14] @ r8 = back2 \n"
- "subs r1, r1, r3 @ r1 = w -= f \n"
- "blt 17f @ Skip if less than a full col \n"
- "ldr r4, [r13,#4*20] @ r4 = divY \n"
- "ldr r12,[r13,#4*15] @ r12= fwd2 \n"
- "13: @ for (x = w; x > 0; x--) { \n"
- "ldr r5, [r13,#4*11] @ for (nn = n; nn > 0; n--) { \n"
- "14: @ \n"
- "mov r14,#0 @ r14= v = 0 \n"
- "sub r5, r5, r3, LSL #8 @ for (xx = f; xx > 0; x--) { \n"
- "15: @ \n"
- "add r5, r5, r2, LSL #16 @ for (yy = y; yy > 0; y--) { \n"
- "16: @ \n"
- "ldrb r11,[r0], r6 @ r11= *src src += fwd \n"
- "subs r5, r5, #1<<16 @ xx-- \n"
- "add r14,r14,r11 @ v += r11 \n"
- "bgt 16b @ } \n"
- "sub r0, r0, r7 @ src -= back5 \n"
- "adds r5, r5, #1<<8 @ yy-- \n"
- "blt 15b @ } \n"
- "mul r14,r4, r14 @ r14 = x *= divY \n"
- "mov r14,r14,LSR #16 @ r14 = v >>= 16 \n"
- "strb r14,[r9], #1 @ *d++ = r14 \n"
- "sub r0, r0, r8 @ s -= back2 \n"
- "subs r5, r5, #1 @ n-- \n"
- "bgt 14b @ } \n"
- "add r0, r0, r12 @ s += fwd2 \n"
- "subs r1, r1, r3 @ x -= f \n"
- "bge 13b @ } \n"
- "17: @ Less than a full column left \n"
- "adds r1, r1, r3 @ x += f \n"
- "beq 21f @ if (x == 0) end \n"
- "@ r0 = src \n"
- "@ r1 = x \n"
- "@ r2 = y \n"
- "@ r3 = f \n"
- "@ r4 = factor \n"
- "@ r6 = fwd \n"
- "@ r7 = back5 \n"
- "@ r8 = back2 \n"
- "@STACK:r1,<9>,factor,n,fwd,back,back2,fwd2,divX,back4,fwd4,fwd3,divY,back5,divXY\n"
- "ldr r4, [r13,#4*22] @ r4 = divXY \n"
- "ldr r5, [r13,#4*11] @ for (nn = n; nn > 0; n--) { \n"
- "18: @ \n"
- "mov r14,#0 @ r14= v = 0 \n"
- "sub r5, r5, r1, LSL #8 @ for (xx = x; xx > 0; x--) { \n"
- "19: @ \n"
- "add r5, r5, r2, LSL #16 @ for (yy = y; yy > 0; y--) { \n"
- "20: @ \n"
- "ldrb r11,[r0],r6 @ r11= *src src += fwd \n"
- "subs r5, r5, #1<<16 @ xx-- \n"
- "add r14,r14,r11 @ v += r11 \n"
- "bgt 20b @ } \n"
- "sub r0, r0, r7 @ src -= back5 \n"
- "adds r5, r5, #1<<8 @ yy-- \n"
- "blt 19b @ } \n"
- "mul r14,r4, r14 @ r14= v *= divX \n"
- "mov r14,r14,LSR #16 @ r14= v >>= 16 \n"
- "strb r14,[r9], #1 @ *d++ = r14 \n"
- "sub r0, r0, r8 @ s -= back2 \n"
- "subs r5, r5, #1 @ n-- \n"
- "bgt 18b @ } \n"
- "21: @ \n"
- "ldmfd r13!,{r1,r4-r11,PC} @ pop, return to thumb \n"
- ENTER_THUMB
- );
-}
-
-#endif
-
-void
-fz_subsample_pixmap(fz_context *ctx, fz_pixmap *tile, int factor)
-{
- int dst_w, dst_h, w, h, fwd, fwd2, fwd3, back, back2, x, y, n, xx, yy, nn, f;
- unsigned char *s, *d;
-
- if (!tile)
- return;
- s = d = tile->samples;
- f = 1<<factor;
- w = tile->w;
- h = tile->h;
- n = tile->n;
- dst_w = (w + f-1)>>factor;
- dst_h = (h + f-1)>>factor;
- fwd = w*n;
- back = f*fwd-n;
- back2 = f*n-1;
- fwd2 = (f-1)*n;
- fwd3 = (f-1)*fwd;
- factor *= 2;
-#ifdef ARCH_ARM
- {
- int strayX = w%f;
- int divX = (strayX ? 65536/(strayX*f) : 0);
- int fwd4 = (strayX-1) * n;
- int back4 = strayX*n-1;
- int strayY = h%f;
- int divY = (strayY ? 65536/(strayY*f) : 0);
- int back5 = fwd * strayY - n;
- int divXY = (strayY*strayX ? 65536/(strayX*strayY) : 0);
- fz_subsample_pixmap_ARM(s, w, h, f, factor, n, fwd, back,
- back2, fwd2, divX, back4, fwd4, fwd3,
- divY, back5, divXY);
- }
-#else
- for (y = h - f; y >= 0; y -= f)
- {
- for (x = w - f; x >= 0; x -= f)
- {
- for (nn = n; nn > 0; nn--)
- {
- int v = 0;
- for (xx = f; xx > 0; xx--)
- {
- for (yy = f; yy > 0; yy--)
- {
- v += *s;
- s += fwd;
- }
- s -= back;
- }
- *d++ = v >> factor;
- s -= back2;
- }
- s += fwd2;
- }
- /* Do any strays */
- x += f;
- if (x > 0)
- {
- int div = x * f;
- int fwd4 = (x-1) * n;
- int back4 = x*n-1;
- for (nn = n; nn > 0; nn--)
- {
- int v = 0;
- for (xx = x; xx > 0; xx--)
- {
- for (yy = f; yy > 0; yy--)
- {
- v += *s;
- s += fwd;
- }
- s -= back;
- }
- *d++ = v / div;
- s -= back4;
- }
- s += fwd4;
- }
- s += fwd3;
- }
- /* Do any stray line */
- y += f;
- if (y > 0)
- {
- int div = y * f;
- int back5 = fwd * y - n;
- for (x = w - f; x >= 0; x -= f)
- {
- for (nn = n; nn > 0; nn--)
- {
- int v = 0;
- for (xx = f; xx > 0; xx--)
- {
- for (yy = y; yy > 0; yy--)
- {
- v += *s;
- s += fwd;
- }
- s -= back5;
- }
- *d++ = v / div;
- s -= back2;
- }
- s += fwd2;
- }
- /* Do any stray at the end of the stray line */
- x += f;
- if (x > 0)
- {
- div = x * y;
- for (nn = n; nn > 0; nn--)
- {
- int v = 0;
- for (xx = x; xx > 0; xx--)
- {
- for (yy = y; yy > 0; yy--)
- {
- v += *s;
- s += fwd;
- }
- s -= back5;
- }
- *d++ = v / div;
- s -= back2;
- }
- }
- }
-#endif
- tile->w = dst_w;
- tile->h = dst_h;
- tile->samples = fz_resize_array(ctx, tile->samples, dst_w * n, dst_h);
-}
-
-void
-fz_pixmap_set_resolution(fz_pixmap *pix, int res)
-{
- pix->xres = res;
- pix->yres = res;
-}
-
-void
-fz_md5_pixmap(fz_pixmap *pix, unsigned char digest[16])
-{
- 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/res_pwg.c b/fitz/res_pwg.c
deleted file mode 100644
index fe1fcd2e..00000000
--- a/fitz/res_pwg.c
+++ /dev/null
@@ -1,318 +0,0 @@
-#include "mupdf/fitz.h"
-
-void
-fz_output_pwg_file_header(fz_output *out)
-{
- static const unsigned char pwgsig[4] = { 'R', 'a', 'S', '2' };
-
- /* Sync word */
- fz_write(out, pwgsig, 4);
-}
-
-static void
-output_header(fz_output *out, const fz_pwg_options *pwg, int xres, int yres, int w, int h, int bpp)
-{
- static const char zero[64] = { 0 };
- int i;
-
- /* Page Header: */
- fz_write(out, pwg ? pwg->media_class : zero, 64);
- fz_write(out, pwg ? pwg->media_color : zero, 64);
- fz_write(out, pwg ? pwg->media_type : zero, 64);
- fz_write(out, pwg ? pwg->output_type : zero, 64);
- fz_write_int32be(out, pwg ? pwg->advance_distance : 0);
- fz_write_int32be(out, pwg ? pwg->advance_media : 0);
- fz_write_int32be(out, pwg ? pwg->collate : 0);
- fz_write_int32be(out, pwg ? pwg->cut_media : 0);
- fz_write_int32be(out, pwg ? pwg->duplex : 0);
- fz_write_int32be(out, xres);
- fz_write_int32be(out, yres);
- /* CUPS format says that 284->300 are supposed to be the bbox of the
- * page in points. PWG says 'Reserved'. */
- for (i=284; i < 300; i += 4)
- fz_write(out, zero, 4);
- fz_write_int32be(out, pwg ? pwg->insert_sheet : 0);
- fz_write_int32be(out, pwg ? pwg->jog : 0);
- fz_write_int32be(out, pwg ? pwg->leading_edge : 0);
- /* CUPS format says that 312->320 are supposed to be the margins of
- * the lower left hand edge of page in points. PWG says 'Reserved'. */
- for (i=312; i < 320; i += 4)
- fz_write(out, zero, 4);
- fz_write_int32be(out, pwg ? pwg->manual_feed : 0);
- fz_write_int32be(out, pwg ? pwg->media_position : 0);
- fz_write_int32be(out, pwg ? pwg->media_weight : 0);
- fz_write_int32be(out, pwg ? pwg->mirror_print : 0);
- fz_write_int32be(out, pwg ? pwg->negative_print : 0);
- fz_write_int32be(out, pwg ? pwg->num_copies : 0);
- fz_write_int32be(out, pwg ? pwg->orientation : 0);
- fz_write_int32be(out, pwg ? pwg->output_face_up : 0);
- fz_write_int32be(out, w * 72/ xres); /* Page size in points */
- fz_write_int32be(out, h * 72/ yres);
- fz_write_int32be(out, pwg ? pwg->separations : 0);
- fz_write_int32be(out, pwg ? pwg->tray_switch : 0);
- fz_write_int32be(out, pwg ? pwg->tumble : 0);
- fz_write_int32be(out, w); /* Page image in pixels */
- fz_write_int32be(out, h);
- fz_write_int32be(out, pwg ? pwg->media_type_num : 0);
- fz_write_int32be(out, bpp < 8 ? 1 : 8); /* Bits per color */
- fz_write_int32be(out, bpp); /* Bits per pixel */
- fz_write_int32be(out, (w * bpp + 7)/8); /* Bytes per line */
- fz_write_int32be(out, 0); /* Chunky pixels */
- fz_write_int32be(out, bpp == 1 ? 3 /* Black */ : (bpp == 8 ? 18 /* Sgray */ : 19 /* Srgb */)); /* Colorspace */
- fz_write_int32be(out, pwg ? pwg->compression : 0);
- fz_write_int32be(out, pwg ? pwg->row_count : 0);
- fz_write_int32be(out, pwg ? pwg->row_feed : 0);
- fz_write_int32be(out, pwg ? pwg->row_step : 0);
- fz_write_int32be(out, bpp <= 8 ? 1 : 3); /* Num Colors */
- for (i=424; i < 452; i += 4)
- fz_write(out, zero, 4);
- fz_write_int32be(out, 1); /* TotalPageCount */
- fz_write_int32be(out, 1); /* CrossFeedTransform */
- fz_write_int32be(out, 1); /* FeedTransform */
- fz_write_int32be(out, 0); /* ImageBoxLeft */
- fz_write_int32be(out, 0); /* ImageBoxTop */
- fz_write_int32be(out, w); /* ImageBoxRight */
- fz_write_int32be(out, h); /* ImageBoxBottom */
- for (i=480; i < 1668; i += 4)
- fz_write(out, zero, 4);
- fz_write(out, pwg ? pwg->rendering_intent : zero, 64);
- fz_write(out, pwg ? pwg->page_size_name : zero, 64);
-}
-
-void
-fz_output_pwg_page(fz_output *out, const fz_pixmap *pixmap, const fz_pwg_options *pwg)
-{
- unsigned char *sp;
- int y, x, sn, dn, ss;
- fz_context *ctx;
-
- if (!out || !pixmap)
- return;
-
- ctx = out->ctx;
-
- if (pixmap->n != 1 && pixmap->n != 2 && pixmap->n != 4)
- fz_throw(ctx, FZ_ERROR_GENERIC, "pixmap must be grayscale or rgb to write as pwg");
-
- sn = pixmap->n;
- dn = pixmap->n;
- if (dn == 2 || dn == 4)
- dn--;
-
- output_header(out, pwg, pixmap->xres, pixmap->yres, pixmap->w, pixmap->h, dn*8);
-
- /* Now output the actual bitmap, using a packbits like compression */
- sp = pixmap->samples;
- ss = pixmap->w * sn;
- y = 0;
- while (y < pixmap->h)
- {
- int yrep;
-
- assert(sp == pixmap->samples + y * ss);
-
- /* Count the number of times this line is repeated */
- for (yrep = 1; yrep < 256 && y+yrep < pixmap->h; yrep++)
- {
- if (memcmp(sp, sp + yrep * ss, ss) != 0)
- break;
- }
- fz_write_byte(out, yrep-1);
-
- /* Encode the line */
- x = 0;
- while (x < pixmap->w)
- {
- int d;
-
- assert(sp == pixmap->samples + y * ss + x * sn);
-
- /* How far do we have to look to find a repeated value? */
- for (d = 1; d < 128 && x+d < pixmap->w; d++)
- {
- if (memcmp(sp + (d-1)*sn, sp + d*sn, sn) == 0)
- break;
- }
- if (d == 1)
- {
- int xrep;
-
- /* We immediately have a repeat (or we've hit
- * the end of the line). Count the number of
- * times this value is repeated. */
- for (xrep = 1; xrep < 128 && x+xrep < pixmap->w; xrep++)
- {
- if (memcmp(sp, sp + xrep*sn, sn) != 0)
- break;
- }
- fz_write_byte(out, xrep-1);
- fz_write(out, sp, dn);
- sp += sn*xrep;
- x += xrep;
- }
- else
- {
- fz_write_byte(out, 257-d);
- x += d;
- while (d > 0)
- {
- fz_write(out, sp, dn);
- sp += sn;
- d--;
- }
- }
- }
-
- /* Move to the next line */
- sp += ss*(yrep-1);
- y += yrep;
- }
-}
-
-void
-fz_output_pwg_bitmap_page(fz_output *out, const fz_bitmap *bitmap, const fz_pwg_options *pwg)
-{
- unsigned char *sp;
- int y, x, ss;
- int byte_width;
-
- if (!out || !bitmap)
- return;
-
- output_header(out, pwg, bitmap->xres, bitmap->yres, bitmap->w, bitmap->h, 1);
-
- /* Now output the actual bitmap, using a packbits like compression */
- sp = bitmap->samples;
- ss = bitmap->stride;
- byte_width = (bitmap->w+7)/8;
- y = 0;
- while (y < bitmap->h)
- {
- int yrep;
-
- assert(sp == bitmap->samples + y * ss);
-
- /* Count the number of times this line is repeated */
- for (yrep = 1; yrep < 256 && y+yrep < bitmap->h; yrep++)
- {
- if (memcmp(sp, sp + yrep * ss, byte_width) != 0)
- break;
- }
- fz_write_byte(out, yrep-1);
-
- /* Encode the line */
- x = 0;
- while (x < byte_width)
- {
- int d;
-
- assert(sp == bitmap->samples + y * ss + x);
-
- /* How far do we have to look to find a repeated value? */
- for (d = 1; d < 128 && x+d < byte_width; d++)
- {
- if (sp[d-1] == sp[d])
- break;
- }
- if (d == 1)
- {
- int xrep;
-
- /* We immediately have a repeat (or we've hit
- * the end of the line). Count the number of
- * times this value is repeated. */
- for (xrep = 1; xrep < 128 && x+xrep < byte_width; xrep++)
- {
- if (sp[0] != sp[xrep])
- break;
- }
- fz_write_byte(out, xrep-1);
- fz_write(out, sp, 1);
- sp += xrep;
- x += xrep;
- }
- else
- {
- fz_write_byte(out, 257-d);
- fz_write(out, sp, d);
- sp += d;
- x += d;
- }
- }
-
- /* Move to the next line */
- sp += ss*yrep - byte_width;
- y += yrep;
- }
-}
-
-void
-fz_output_pwg(fz_output *out, const fz_pixmap *pixmap, const fz_pwg_options *pwg)
-{
- fz_output_pwg_file_header(out);
- fz_output_pwg_page(out, pixmap, pwg);
-}
-
-void
-fz_write_pwg(fz_context *ctx, fz_pixmap *pixmap, char *filename, int append, const fz_pwg_options *pwg)
-{
- FILE *fp;
- fz_output *out = NULL;
-
- fp = fopen(filename, append ? "ab" : "wb");
- if (!fp)
- {
- fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open file '%s': %s", filename, strerror(errno));
- }
-
- fz_var(out);
-
- fz_try(ctx)
- {
- out = fz_new_output_with_file(ctx, fp);
- if (!append)
- fz_output_pwg_file_header(out);
- fz_output_pwg_page(out, pixmap, pwg);
- }
- fz_always(ctx)
- {
- fz_close_output(out);
- fclose(fp);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
-}
-
-void
-fz_write_pwg_bitmap(fz_context *ctx, fz_bitmap *bitmap, char *filename, int append, const fz_pwg_options *pwg)
-{
- FILE *fp;
- fz_output *out = NULL;
-
- fp = fopen(filename, append ? "ab" : "wb");
- if (!fp)
- {
- fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open file '%s': %s", filename, strerror(errno));
- }
-
- fz_var(out);
-
- fz_try(ctx)
- {
- out = fz_new_output_with_file(ctx, fp);
- if (!append)
- fz_output_pwg_file_header(out);
- fz_output_pwg_bitmap_page(out, bitmap, pwg);
- }
- fz_always(ctx)
- {
- fz_close_output(out);
- fclose(fp);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
-}
diff --git a/fitz/res_shade.c b/fitz/res_shade.c
deleted file mode 100644
index b13dc215..00000000
--- a/fitz/res_shade.c
+++ /dev/null
@@ -1,1096 +0,0 @@
-#include "mupdf/fitz.h"
-
-#define SWAP(a,b) {fz_vertex *t = (a); (a) = (b); (b) = t;}
-
-static void
-paint_tri(fz_mesh_processor *painter, fz_vertex *v0, fz_vertex *v1, fz_vertex *v2)
-{
- painter->process(painter->process_arg, v0, v1, v2);
-}
-
-static void
-paint_quad(fz_mesh_processor *painter, fz_vertex *v0, fz_vertex *v1, fz_vertex *v2, fz_vertex *v3)
-{
- /* For a quad with corners (in clockwise or anticlockwise order) are
- * v0, v1, v2, v3. We can choose to split in in various different ways.
- * Arbitrarily we can pick v0, v1, v3 for the first triangle. We then
- * have to choose between v1, v2, v3 or v3, v2, v1 (or their equivalent
- * rotations) for the second triangle.
- *
- * v1, v2, v3 has the property that both triangles share the same
- * winding (useful if we were ever doing simple back face culling).
- *
- * v3, v2, v1 has the property that all the 'shared' edges (both
- * within this quad, and with adjacent quads) are walked in the same
- * direction every time. This can be useful in that depending on the
- * implementation/rounding etc walking from A -> B can hit different
- * pixels than walking from B->A.
- *
- * In the event neither of these things matter at the moment, as all
- * the process functions where it matters order the edges from top to
- * bottom before walking them.
- */
- painter->process(painter->process_arg, v0, v1, v3);
- painter->process(painter->process_arg, v3, v2, v1);
-}
-
-static void
-fz_process_mesh_type1(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_mesh_processor *painter)
-{
- float *p = shade->u.f.fn_vals;
- int xdivs = shade->u.f.xdivs;
- int ydivs = shade->u.f.ydivs;
- float x0 = shade->u.f.domain[0][0];
- float y0 = shade->u.f.domain[0][1];
- float x1 = shade->u.f.domain[1][0];
- float y1 = shade->u.f.domain[1][1];
- int xx, yy;
- float y, yn, x;
- fz_vertex vs[2][2];
- fz_vertex *v = vs[0];
- fz_vertex *vn = vs[1];
- int n = shade->colorspace->n;
- fz_matrix local_ctm;
-
- fz_concat(&local_ctm, &shade->u.f.matrix, ctm);
-
- y = y0;
- for (yy = 0; yy < ydivs; yy++)
- {
- yn = y0 + (y1 - y0) * (yy + 1) / ydivs;
-
- x = x0;
- v[0].p.x = x; v[0].p.y = y;
- fz_transform_point(&v[0].p, &local_ctm);
- memcpy(v[0].c, p, n*sizeof(float));
- p += n;
- v[1].p.x = x; v[1].p.y = yn;
- fz_transform_point(&v[1].p, &local_ctm);
- memcpy(v[1].c, p + xdivs*n, n*sizeof(float));
- for (xx = 0; xx < xdivs; xx++)
- {
- x = x0 + (x1 - x0) * (xx + 1) / xdivs;
-
- vn[0].p.x = x; vn[0].p.y = y;
- fz_transform_point(&vn[0].p, &local_ctm);
- memcpy(vn[0].c, p, n*sizeof(float));
- p += n;
- vn[1].p.x = x; vn[1].p.y = yn;
- fz_transform_point(&vn[1].p, &local_ctm);
- memcpy(vn[1].c, p + xdivs*n, n*sizeof(float));
-
- paint_quad(painter, &v[0], &vn[0], &vn[1], &v[1]);
- SWAP(v,vn);
- }
- y = yn;
- }
-}
-
-/* FIXME: Nasty */
-#define HUGENUM 32000 /* how far to extend linear/radial shadings */
-
-static fz_point
-fz_point_on_circle(fz_point p, float r, float theta)
-{
- p.x = p.x + cosf(theta) * r;
- p.y = p.y + sinf(theta) * r;
-
- return p;
-}
-
-static void
-fz_process_mesh_type2(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_mesh_processor *painter)
-{
- fz_point p0, p1, dir;
- fz_vertex v0, v1, v2, v3;
- fz_vertex e0, e1;
- float theta;
-
- p0.x = shade->u.l_or_r.coords[0][0];
- p0.y = shade->u.l_or_r.coords[0][1];
- p1.x = shade->u.l_or_r.coords[1][0];
- p1.y = shade->u.l_or_r.coords[1][1];
- dir.x = p0.y - p1.y;
- dir.y = p1.x - p0.x;
- fz_transform_point(&p0, ctm);
- fz_transform_point(&p1, ctm);
- fz_transform_vector(&dir, ctm);
- theta = atan2f(dir.y, dir.x);
-
- v0.p = fz_point_on_circle(p0, HUGENUM, theta);
- v1.p = fz_point_on_circle(p1, HUGENUM, theta);
- v2.p = fz_point_on_circle(p0, -HUGENUM, theta);
- v3.p = fz_point_on_circle(p1, -HUGENUM, theta);
-
- v0.c[0] = 0;
- v1.c[0] = 1;
- v2.c[0] = 0;
- v3.c[0] = 1;
-
- paint_quad(painter, &v0, &v2, &v3, &v1);
-
- if (shade->u.l_or_r.extend[0])
- {
- e0.p.x = v0.p.x - (p1.x - p0.x) * HUGENUM;
- e0.p.y = v0.p.y - (p1.y - p0.y) * HUGENUM;
-
- e1.p.x = v2.p.x - (p1.x - p0.x) * HUGENUM;
- e1.p.y = v2.p.y - (p1.y - p0.y) * HUGENUM;
-
- e0.c[0] = 0;
- e1.c[0] = 0;
- v0.c[0] = 0;
- v2.c[0] = 0;
-
- paint_quad(painter, &e0, &v0, &v2, &e1);
- }
-
- if (shade->u.l_or_r.extend[1])
- {
- e0.p.x = v1.p.x + (p1.x - p0.x) * HUGENUM;
- e0.p.y = v1.p.y + (p1.y - p0.y) * HUGENUM;
-
- e1.p.x = v3.p.x + (p1.x - p0.x) * HUGENUM;
- e1.p.y = v3.p.y + (p1.y - p0.y) * HUGENUM;
-
- e0.c[0] = 1;
- e1.c[0] = 1;
- v1.c[0] = 1;
- v3.c[0] = 1;
-
- paint_quad(painter, &e0, &v1, &v3, &e1);
- }
-}
-
-/* FIXME: Nasty */
-#define RADSEGS 32 /* how many segments to generate for radial meshes */
-
-static void
-fz_paint_annulus(const fz_matrix *ctm,
- fz_point p0, float r0, float c0,
- fz_point p1, float r1, float c1,
- fz_mesh_processor *painter)
-{
- fz_vertex t0, t1, t2, t3, b0, b1, b2, b3;
- float theta, step;
- int i;
-
- theta = atan2f(p1.y - p0.y, p1.x - p0.x);
- step = (float)M_PI * 2 / RADSEGS;
-
- for (i = 0; i < RADSEGS / 2; i++)
- {
- t0.p = fz_point_on_circle(p0, r0, theta + i * step);
- t1.p = fz_point_on_circle(p0, r0, theta + i * step + step);
- t2.p = fz_point_on_circle(p1, r1, theta + i * step);
- t3.p = fz_point_on_circle(p1, r1, theta + i * step + step);
- b0.p = fz_point_on_circle(p0, r0, theta - i * step);
- b1.p = fz_point_on_circle(p0, r0, theta - i * step - step);
- b2.p = fz_point_on_circle(p1, r1, theta - i * step);
- b3.p = fz_point_on_circle(p1, r1, theta - i * step - step);
-
- fz_transform_point(&t0.p, ctm);
- fz_transform_point(&t1.p, ctm);
- fz_transform_point(&t2.p, ctm);
- fz_transform_point(&t3.p, ctm);
- fz_transform_point(&b0.p, ctm);
- fz_transform_point(&b1.p, ctm);
- fz_transform_point(&b2.p, ctm);
- fz_transform_point(&b3.p, ctm);
-
- t0.c[0] = c0;
- t1.c[0] = c0;
- t2.c[0] = c1;
- t3.c[0] = c1;
- b0.c[0] = c0;
- b1.c[0] = c0;
- b2.c[0] = c1;
- b3.c[0] = c1;
-
- paint_quad(painter, &t0, &t2, &t3, &t1);
- paint_quad(painter, &b0, &b2, &b3, &b1);
- }
-}
-
-static void
-fz_process_mesh_type3(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_mesh_processor *painter)
-{
- fz_point p0, p1;
- float r0, r1;
- fz_point e;
- float er, rs;
-
- p0.x = shade->u.l_or_r.coords[0][0];
- p0.y = shade->u.l_or_r.coords[0][1];
- r0 = shade->u.l_or_r.coords[0][2];
-
- p1.x = shade->u.l_or_r.coords[1][0];
- p1.y = shade->u.l_or_r.coords[1][1];
- r1 = shade->u.l_or_r.coords[1][2];
-
- if (shade->u.l_or_r.extend[0])
- {
- if (r0 < r1)
- rs = r0 / (r0 - r1);
- else
- rs = -HUGENUM;
-
- e.x = p0.x + (p1.x - p0.x) * rs;
- e.y = p0.y + (p1.y - p0.y) * rs;
- er = r0 + (r1 - r0) * rs;
-
- fz_paint_annulus(ctm, e, er, 0, p0, r0, 0, painter);
- }
-
- fz_paint_annulus(ctm, p0, r0, 0, p1, r1, 1, painter);
-
- if (shade->u.l_or_r.extend[1])
- {
- if (r0 > r1)
- rs = r1 / (r1 - r0);
- else
- rs = -HUGENUM;
-
- e.x = p1.x + (p0.x - p1.x) * rs;
- e.y = p1.y + (p0.y - p1.y) * rs;
- er = r1 + (r0 - r1) * rs;
-
- fz_paint_annulus(ctm, p1, r1, 1, e, er, 1, painter);
- }
-}
-
-static inline float read_sample(fz_stream *stream, int bits, float min, float max)
-{
- /* we use pow(2,x) because (1<<x) would overflow the math on 32-bit samples */
- float bitscale = 1 / (powf(2, bits) - 1);
- return min + fz_read_bits(stream, bits) * (max - min) * bitscale;
-}
-
-static void
-fz_process_mesh_type4(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_mesh_processor *painter)
-{
- fz_stream *stream = fz_open_compressed_buffer(ctx, shade->buffer);
- fz_vertex v[4];
- fz_vertex *va = &v[0];
- fz_vertex *vb = &v[1];
- fz_vertex *vc = &v[2];
- fz_vertex *vd = &v[3];
- int flag, i, ncomp = painter->ncomp;
- int bpflag = shade->u.m.bpflag;
- int bpcoord = shade->u.m.bpcoord;
- int bpcomp = shade->u.m.bpcomp;
- float x0 = shade->u.m.x0;
- float x1 = shade->u.m.x1;
- float y0 = shade->u.m.y0;
- float y1 = shade->u.m.y1;
- float *c0 = shade->u.m.c0;
- float *c1 = shade->u.m.c1;
-
- fz_try(ctx)
- {
- while (!fz_is_eof_bits(stream))
- {
- flag = fz_read_bits(stream, bpflag);
- vd->p.x = read_sample(stream, bpcoord, x0, x1);
- vd->p.y = read_sample(stream, bpcoord, y0, y1);
- fz_transform_point(&vd->p, ctm);
- for (i = 0; i < ncomp; i++)
- vd->c[i] = read_sample(stream, bpcomp, c0[i], c1[i]);
-
- switch (flag)
- {
- case 0: /* start new triangle */
- SWAP(va, vd);
-
- fz_read_bits(stream, bpflag);
- vb->p.x = read_sample(stream, bpcoord, x0, x1);
- vb->p.y = read_sample(stream, bpcoord, y0, y1);
- fz_transform_point(&vb->p, ctm);
- for (i = 0; i < ncomp; i++)
- vb->c[i] = read_sample(stream, bpcomp, c0[i], c1[i]);
-
- fz_read_bits(stream, bpflag);
- vc->p.x = read_sample(stream, bpcoord, x0, x1);
- vc->p.y = read_sample(stream, bpcoord, y0, y1);
- fz_transform_point(&vc->p, ctm);
- for (i = 0; i < ncomp; i++)
- vc->c[i] = read_sample(stream, bpcomp, c0[i], c1[i]);
-
- paint_tri(painter, va, vb, vc);
- break;
-
- case 1: /* Vb, Vc, Vd */
- SWAP(va, vb);
- SWAP(vb, vc);
- SWAP(vc, vd);
- paint_tri(painter, va, vb, vc);
- break;
-
- case 2: /* Va, Vc, Vd */
- SWAP(vb, vc);
- SWAP(vc, vd);
- paint_tri(painter, va, vb, vc);
- break;
- }
- }
- }
- fz_always(ctx)
- {
- fz_close(stream);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
-}
-
-static void
-fz_process_mesh_type5(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_mesh_processor *painter)
-{
- fz_stream *stream = fz_open_compressed_buffer(ctx, shade->buffer);
- fz_vertex *buf = NULL;
- fz_vertex *ref = NULL;
- int first;
- int ncomp = painter->ncomp;
- int i, k;
- int vprow = shade->u.m.vprow;
- int bpcoord = shade->u.m.bpcoord;
- int bpcomp = shade->u.m.bpcomp;
- float x0 = shade->u.m.x0;
- float x1 = shade->u.m.x1;
- float y0 = shade->u.m.y0;
- float y1 = shade->u.m.y1;
- float *c0 = shade->u.m.c0;
- float *c1 = shade->u.m.c1;
-
- fz_var(buf);
- fz_var(ref);
-
- fz_try(ctx)
- {
- ref = fz_malloc_array(ctx, vprow, sizeof(fz_vertex));
- buf = fz_malloc_array(ctx, vprow, sizeof(fz_vertex));
- first = 1;
-
- while (!fz_is_eof_bits(stream))
- {
- for (i = 0; i < vprow; i++)
- {
- buf[i].p.x = read_sample(stream, bpcoord, x0, x1);
- buf[i].p.y = read_sample(stream, bpcoord, y0, y1);
- fz_transform_point(&buf[i].p, ctm);
- for (k = 0; k < ncomp; k++)
- buf[i].c[k] = read_sample(stream, bpcomp, c0[k], c1[k]);
- }
-
- if (!first)
- for (i = 0; i < vprow - 1; i++)
- paint_quad(painter, &ref[i], &ref[i+1], &buf[i+1], &buf[i]);
-
- SWAP(ref,buf);
- first = 0;
- }
- }
- fz_always(ctx)
- {
- fz_free(ctx, ref);
- fz_free(ctx, buf);
- fz_close(stream);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
-}
-
-/* Subdivide and tessellate tensor-patches */
-
-typedef struct tensor_patch_s tensor_patch;
-
-struct tensor_patch_s
-{
- fz_point pole[4][4];
- float color[4][FZ_MAX_COLORS];
-};
-
-static void
-triangulate_patch(fz_mesh_processor *painter, tensor_patch p)
-{
- fz_vertex v0, v1, v2, v3;
- int col_len = painter->ncomp * sizeof(v0.c[0]);
-
- v0.p = p.pole[0][0];
- memcpy(v0.c, p.color[0], col_len);
-
- v1.p = p.pole[0][3];
- memcpy(v1.c, p.color[1], col_len);
-
- v2.p = p.pole[3][3];
- memcpy(v2.c, p.color[2], col_len);
-
- v3.p = p.pole[3][0];
- memcpy(v3.c, p.color[3], col_len);
-
- paint_quad(painter, &v0, &v1, &v2, &v3);
-}
-
-static inline void midcolor(float *c, float *c1, float *c2, int n)
-{
- int i;
- for (i = 0; i < n; i++)
- c[i] = (c1[i] + c2[i]) * 0.5f;
-}
-
-static void
-split_curve(fz_point *pole, fz_point *q0, fz_point *q1, int polestep)
-{
- /*
- split bezier curve given by control points pole[0]..pole[3]
- using de casteljau algo at midpoint and build two new
- bezier curves q0[0]..q0[3] and q1[0]..q1[3]. all indices
- should be multiplies by polestep == 1 for vertical bezier
- curves in patch and == 4 for horizontal bezier curves due
- to C's multi-dimensional matrix memory layout.
- */
-
- float x12 = (pole[1 * polestep].x + pole[2 * polestep].x) * 0.5f;
- float y12 = (pole[1 * polestep].y + pole[2 * polestep].y) * 0.5f;
-
- q0[1 * polestep].x = (pole[0 * polestep].x + pole[1 * polestep].x) * 0.5f;
- q0[1 * polestep].y = (pole[0 * polestep].y + pole[1 * polestep].y) * 0.5f;
- q1[2 * polestep].x = (pole[2 * polestep].x + pole[3 * polestep].x) * 0.5f;
- q1[2 * polestep].y = (pole[2 * polestep].y + pole[3 * polestep].y) * 0.5f;
-
- q0[2 * polestep].x = (q0[1 * polestep].x + x12) * 0.5f;
- q0[2 * polestep].y = (q0[1 * polestep].y + y12) * 0.5f;
- q1[1 * polestep].x = (x12 + q1[2 * polestep].x) * 0.5f;
- q1[1 * polestep].y = (y12 + q1[2 * polestep].y) * 0.5f;
-
- q0[3 * polestep].x = (q0[2 * polestep].x + q1[1 * polestep].x) * 0.5f;
- q0[3 * polestep].y = (q0[2 * polestep].y + q1[1 * polestep].y) * 0.5f;
- q1[0 * polestep].x = (q0[2 * polestep].x + q1[1 * polestep].x) * 0.5f;
- q1[0 * polestep].y = (q0[2 * polestep].y + q1[1 * polestep].y) * 0.5f;
-
- q0[0 * polestep].x = pole[0 * polestep].x;
- q0[0 * polestep].y = pole[0 * polestep].y;
- q1[3 * polestep].x = pole[3 * polestep].x;
- q1[3 * polestep].y = pole[3 * polestep].y;
-}
-
-static void
-split_stripe(tensor_patch *p, tensor_patch *s0, tensor_patch *s1, int n)
-{
- /*
- split all horizontal bezier curves in patch,
- creating two new patches with half the width.
- */
- split_curve(&p->pole[0][0], &s0->pole[0][0], &s1->pole[0][0], 4);
- split_curve(&p->pole[0][1], &s0->pole[0][1], &s1->pole[0][1], 4);
- split_curve(&p->pole[0][2], &s0->pole[0][2], &s1->pole[0][2], 4);
- split_curve(&p->pole[0][3], &s0->pole[0][3], &s1->pole[0][3], 4);
-
- /* interpolate the colors for the two new patches. */
- memcpy(s0->color[0], p->color[0], n * sizeof(s0->color[0][0]));
- memcpy(s0->color[1], p->color[1], n * sizeof(s0->color[1][0]));
- midcolor(s0->color[2], p->color[1], p->color[2], n);
- midcolor(s0->color[3], p->color[0], p->color[3], n);
-
- memcpy(s1->color[0], s0->color[3], n * sizeof(s1->color[0][0]));
- memcpy(s1->color[1], s0->color[2], n * sizeof(s1->color[1][0]));
- memcpy(s1->color[2], p->color[2], n * sizeof(s1->color[2][0]));
- memcpy(s1->color[3], p->color[3], n * sizeof(s1->color[3][0]));
-}
-
-static void
-draw_stripe(fz_mesh_processor *painter, tensor_patch *p, int depth)
-{
- tensor_patch s0, s1;
-
- /* split patch into two half-height patches */
- split_stripe(p, &s0, &s1, painter->ncomp);
-
- depth--;
- if (depth == 0)
- {
- /* if no more subdividing, draw two new patches... */
- triangulate_patch(painter, s1);
- triangulate_patch(painter, s0);
- }
- else
- {
- /* ...otherwise, continue subdividing. */
- draw_stripe(painter, &s1, depth);
- draw_stripe(painter, &s0, depth);
- }
-}
-
-static void
-split_patch(tensor_patch *p, tensor_patch *s0, tensor_patch *s1, int n)
-{
- /*
- split all vertical bezier curves in patch,
- creating two new patches with half the height.
- */
- split_curve(p->pole[0], s0->pole[0], s1->pole[0], 1);
- split_curve(p->pole[1], s0->pole[1], s1->pole[1], 1);
- split_curve(p->pole[2], s0->pole[2], s1->pole[2], 1);
- split_curve(p->pole[3], s0->pole[3], s1->pole[3], 1);
-
- /* interpolate the colors for the two new patches. */
- memcpy(s0->color[0], p->color[0], n * sizeof(s0->color[0][0]));
- midcolor(s0->color[1], p->color[0], p->color[1], n);
- midcolor(s0->color[2], p->color[2], p->color[3], n);
- memcpy(s0->color[3], p->color[3], n * sizeof(s0->color[3][0]));
-
- memcpy(s1->color[0], s0->color[1], n * sizeof(s1->color[0][0]));
- memcpy(s1->color[1], p->color[1], n * sizeof(s1->color[1][0]));
- memcpy(s1->color[2], p->color[2], n * sizeof(s1->color[2][0]));
- memcpy(s1->color[3], s0->color[2], n * sizeof(s1->color[3][0]));
-}
-
-static void
-draw_patch(fz_mesh_processor *painter, tensor_patch *p, int depth, int origdepth)
-{
- tensor_patch s0, s1;
-
- /* split patch into two half-width patches */
- split_patch(p, &s0, &s1, painter->ncomp);
-
- depth--;
- if (depth == 0)
- {
- /* if no more subdividing, draw two new patches... */
- draw_stripe(painter, &s0, origdepth);
- draw_stripe(painter, &s1, origdepth);
- }
- else
- {
- /* ...otherwise, continue subdividing. */
- draw_patch(painter, &s0, depth, origdepth);
- draw_patch(painter, &s1, depth, origdepth);
- }
-}
-
-static fz_point
-compute_tensor_interior(
- fz_point a, fz_point b, fz_point c, fz_point d,
- fz_point e, fz_point f, fz_point g, fz_point h)
-{
- fz_point pt;
-
- /* see equations at page 330 in pdf 1.7 */
-
- pt.x = -4 * a.x;
- pt.x += 6 * (b.x + c.x);
- pt.x += -2 * (d.x + e.x);
- pt.x += 3 * (f.x + g.x);
- pt.x += -1 * h.x;
- pt.x /= 9;
-
- pt.y = -4 * a.y;
- pt.y += 6 * (b.y + c.y);
- pt.y += -2 * (d.y + e.y);
- pt.y += 3 * (f.y + g.y);
- pt.y += -1 * h.y;
- pt.y /= 9;
-
- return pt;
-}
-
-static void
-make_tensor_patch(tensor_patch *p, int type, fz_point *pt)
-{
- if (type == 6)
- {
- /* see control point stream order at page 325 in pdf 1.7 */
-
- p->pole[0][0] = pt[0];
- p->pole[0][1] = pt[1];
- p->pole[0][2] = pt[2];
- p->pole[0][3] = pt[3];
- p->pole[1][3] = pt[4];
- p->pole[2][3] = pt[5];
- p->pole[3][3] = pt[6];
- p->pole[3][2] = pt[7];
- p->pole[3][1] = pt[8];
- p->pole[3][0] = pt[9];
- p->pole[2][0] = pt[10];
- p->pole[1][0] = pt[11];
-
- /* see equations at page 330 in pdf 1.7 */
-
- p->pole[1][1] = compute_tensor_interior(
- p->pole[0][0], p->pole[0][1], p->pole[1][0], p->pole[0][3],
- p->pole[3][0], p->pole[3][1], p->pole[1][3], p->pole[3][3]);
-
- p->pole[1][2] = compute_tensor_interior(
- p->pole[0][3], p->pole[0][2], p->pole[1][3], p->pole[0][0],
- p->pole[3][3], p->pole[3][2], p->pole[1][0], p->pole[3][0]);
-
- p->pole[2][1] = compute_tensor_interior(
- p->pole[3][0], p->pole[3][1], p->pole[2][0], p->pole[3][3],
- p->pole[0][0], p->pole[0][1], p->pole[2][3], p->pole[0][3]);
-
- p->pole[2][2] = compute_tensor_interior(
- p->pole[3][3], p->pole[3][2], p->pole[2][3], p->pole[3][0],
- p->pole[0][3], p->pole[0][2], p->pole[2][0], p->pole[0][0]);
- }
- else if (type == 7)
- {
- /* see control point stream order at page 330 in pdf 1.7 */
-
- p->pole[0][0] = pt[0];
- p->pole[0][1] = pt[1];
- p->pole[0][2] = pt[2];
- p->pole[0][3] = pt[3];
- p->pole[1][3] = pt[4];
- p->pole[2][3] = pt[5];
- p->pole[3][3] = pt[6];
- p->pole[3][2] = pt[7];
- p->pole[3][1] = pt[8];
- p->pole[3][0] = pt[9];
- p->pole[2][0] = pt[10];
- p->pole[1][0] = pt[11];
- p->pole[1][1] = pt[12];
- p->pole[1][2] = pt[13];
- p->pole[2][2] = pt[14];
- p->pole[2][1] = pt[15];
- }
-}
-
-/* FIXME: Nasty */
-#define SUBDIV 3 /* how many levels to subdivide patches */
-
-static void
-fz_process_mesh_type6(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_mesh_processor *painter)
-{
- fz_stream *stream = fz_open_compressed_buffer(ctx, shade->buffer);
- float color_storage[2][4][FZ_MAX_COLORS];
- fz_point point_storage[2][12];
- int store = 0;
- int ncomp = painter->ncomp;
- int i, k;
- int bpflag = shade->u.m.bpflag;
- int bpcoord = shade->u.m.bpcoord;
- int bpcomp = shade->u.m.bpcomp;
- float x0 = shade->u.m.x0;
- float x1 = shade->u.m.x1;
- float y0 = shade->u.m.y0;
- float y1 = shade->u.m.y1;
- float *c0 = shade->u.m.c0;
- float *c1 = shade->u.m.c1;
-
- fz_try(ctx)
- {
- float (*prevc)[FZ_MAX_COLORS] = NULL;
- fz_point *prevp = NULL;
- while (!fz_is_eof_bits(stream))
- {
- float (*c)[FZ_MAX_COLORS] = color_storage[store];
- fz_point *v = point_storage[store];
- int startcolor;
- int startpt;
- int flag;
- tensor_patch patch;
-
- flag = fz_read_bits(stream, bpflag);
-
- if (flag == 0)
- {
- startpt = 0;
- startcolor = 0;
- }
- else
- {
- startpt = 4;
- startcolor = 2;
- }
-
- for (i = startpt; i < 12; i++)
- {
- v[i].x = read_sample(stream, bpcoord, x0, x1);
- v[i].y = read_sample(stream, bpcoord, y0, y1);
- fz_transform_point(&v[i], ctm);
- }
-
- for (i = startcolor; i < 4; i++)
- {
- for (k = 0; k < ncomp; k++)
- c[i][k] = read_sample(stream, bpcomp, c0[k], c1[k]);
- }
-
- if (flag == 0)
- {
- }
- else if (flag == 1 && prevc)
- {
- v[0] = prevp[3];
- v[1] = prevp[4];
- v[2] = prevp[5];
- v[3] = prevp[6];
- memcpy(c[0], prevc[1], ncomp * sizeof(float));
- memcpy(c[1], prevc[2], ncomp * sizeof(float));
- }
- else if (flag == 2 && prevc)
- {
- v[0] = prevp[6];
- v[1] = prevp[7];
- v[2] = prevp[8];
- v[3] = prevp[9];
- memcpy(c[0], prevc[2], ncomp * sizeof(float));
- memcpy(c[1], prevc[3], ncomp * sizeof(float));
- }
- else if (flag == 3 && prevc)
- {
- v[0] = prevp[ 9];
- v[1] = prevp[10];
- v[2] = prevp[11];
- v[3] = prevp[ 0];
- memcpy(c[0], prevc[3], ncomp * sizeof(float));
- memcpy(c[1], prevc[0], ncomp * sizeof(float));
- }
- else
- continue;
-
- make_tensor_patch(&patch, 6, v);
-
- for (i = 0; i < 4; i++)
- memcpy(patch.color[i], c[i], ncomp * sizeof(float));
-
- draw_patch(painter, &patch, SUBDIV, SUBDIV);
-
- prevp = v;
- prevc = c;
- store ^= 1;
- }
- }
- fz_always(ctx)
- {
- fz_close(stream);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
-}
-
-static void
-fz_process_mesh_type7(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_mesh_processor *painter)
-{
- fz_stream *stream = fz_open_compressed_buffer(ctx, shade->buffer);
- int bpflag = shade->u.m.bpflag;
- int bpcoord = shade->u.m.bpcoord;
- int bpcomp = shade->u.m.bpcomp;
- float x0 = shade->u.m.x0;
- float x1 = shade->u.m.x1;
- float y0 = shade->u.m.y0;
- float y1 = shade->u.m.y1;
- float *c0 = shade->u.m.c0;
- float *c1 = shade->u.m.c1;
- float color_storage[2][4][FZ_MAX_COLORS];
- fz_point point_storage[2][16];
- int store = 0;
- int ncomp = painter->ncomp;
- int i, k;
- float (*prevc)[FZ_MAX_COLORS] = NULL;
- fz_point (*prevp) = NULL;
-
- fz_try(ctx)
- {
- while (!fz_is_eof_bits(stream))
- {
- float (*c)[FZ_MAX_COLORS] = color_storage[store];
- fz_point *v = point_storage[store];
- int startcolor;
- int startpt;
- int flag;
- tensor_patch patch;
-
- flag = fz_read_bits(stream, bpflag);
-
- if (flag == 0)
- {
- startpt = 0;
- startcolor = 0;
- }
- else
- {
- startpt = 4;
- startcolor = 2;
- }
-
- for (i = startpt; i < 16; i++)
- {
- v[i].x = read_sample(stream, bpcoord, x0, x1);
- v[i].y = read_sample(stream, bpcoord, y0, y1);
- fz_transform_point(&v[i], ctm);
- }
-
- for (i = startcolor; i < 4; i++)
- {
- for (k = 0; k < ncomp; k++)
- c[i][k] = read_sample(stream, bpcomp, c0[k], c1[k]);
- }
-
- if (flag == 0)
- {
- }
- else if (flag == 1 && prevc)
- {
- v[0] = prevp[3];
- v[1] = prevp[4];
- v[2] = prevp[5];
- v[3] = prevp[6];
- memcpy(c[0], prevc[1], ncomp * sizeof(float));
- memcpy(c[1], prevc[2], ncomp * sizeof(float));
- }
- else if (flag == 2 && prevc)
- {
- v[0] = prevp[6];
- v[1] = prevp[7];
- v[2] = prevp[8];
- v[3] = prevp[9];
- memcpy(c[0], prevc[2], ncomp * sizeof(float));
- memcpy(c[1], prevc[3], ncomp * sizeof(float));
- }
- else if (flag == 3 && prevc)
- {
- v[0] = prevp[ 9];
- v[1] = prevp[10];
- v[2] = prevp[11];
- v[3] = prevp[ 0];
- memcpy(c[0], prevc[3], ncomp * sizeof(float));
- memcpy(c[1], prevc[0], ncomp * sizeof(float));
- }
- else
- continue; /* We have no patch! */
-
- make_tensor_patch(&patch, 7, v);
-
- for (i = 0; i < 4; i++)
- memcpy(patch.color[i], c[i], ncomp * sizeof(float));
-
- draw_patch(painter, &patch, SUBDIV, SUBDIV);
-
- prevp = v;
- prevc = c;
- store ^= 1;
- }
- }
- fz_always(ctx)
- {
- fz_close(stream);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
-}
-
-void
-fz_process_mesh(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm,
- fz_mesh_process_fn *process, void *process_arg)
-{
- fz_mesh_processor painter;
-
- painter.ctx = ctx;
- painter.shade = shade;
- painter.process = process;
- painter.process_arg = process_arg;
- painter.ncomp = (shade->use_function > 0 ? 1 : shade->colorspace->n);
-
- if (shade->type == FZ_FUNCTION_BASED)
- fz_process_mesh_type1(ctx, shade, ctm, &painter);
- else if (shade->type == FZ_LINEAR)
- fz_process_mesh_type2(ctx, shade, ctm, &painter);
- else if (shade->type == FZ_RADIAL)
- fz_process_mesh_type3(ctx, shade, ctm, &painter);
- else if (shade->type == FZ_MESH_TYPE4)
- fz_process_mesh_type4(ctx, shade, ctm, &painter);
- else if (shade->type == FZ_MESH_TYPE5)
- fz_process_mesh_type5(ctx, shade, ctm, &painter);
- else if (shade->type == FZ_MESH_TYPE6)
- fz_process_mesh_type6(ctx, shade, ctm, &painter);
- else if (shade->type == FZ_MESH_TYPE7)
- fz_process_mesh_type7(ctx, shade, ctm, &painter);
- else
- fz_throw(ctx, FZ_ERROR_GENERIC, "Unexpected mesh type %d\n", shade->type);
-}
-
-static fz_rect *
-fz_bound_mesh_type1(fz_context *ctx, fz_shade *shade, fz_rect *bbox)
-{
- bbox->x0 = shade->u.f.domain[0][0];
- bbox->y0 = shade->u.f.domain[0][1];
- bbox->x1 = shade->u.f.domain[1][0];
- bbox->y1 = shade->u.f.domain[1][1];
- return fz_transform_rect(bbox, &shade->u.f.matrix);
-}
-
-static fz_rect *
-fz_bound_mesh_type2(fz_context *ctx, fz_shade *shade, fz_rect *bbox)
-{
- /* FIXME: If axis aligned and not extended, the bbox may only be
- * infinite in one direction */
- *bbox = fz_infinite_rect;
- return bbox;
-}
-
-static fz_rect *
-fz_bound_mesh_type3(fz_context *ctx, fz_shade *shade, fz_rect *bbox)
-{
- fz_point p0, p1;
- float r0, r1;
-
- r0 = shade->u.l_or_r.coords[0][2];
- r1 = shade->u.l_or_r.coords[1][2];
-
- if (shade->u.l_or_r.extend[0])
- {
- if (r0 >= r1)
- {
- *bbox = fz_infinite_rect;
- return bbox;
- }
- }
-
- if (shade->u.l_or_r.extend[1])
- {
- if (r0 <= r1)
- {
- *bbox = fz_infinite_rect;
- return bbox;
- }
- }
-
- p0.x = shade->u.l_or_r.coords[0][0];
- p0.y = shade->u.l_or_r.coords[0][1];
- p1.x = shade->u.l_or_r.coords[1][0];
- p1.y = shade->u.l_or_r.coords[1][1];
-
- bbox->x0 = p0.x - r0; bbox->y0 = p0.y - r0;
- bbox->x1 = p0.x + r0; bbox->y1 = p0.x + r0;
- if (bbox->x0 > p1.x - r1)
- bbox->x0 = p1.x - r1;
- if (bbox->x1 < p1.x + r1)
- bbox->x1 = p1.x + r1;
- if (bbox->y0 > p1.y - r1)
- bbox->y0 = p1.y - r1;
- if (bbox->y1 < p1.y + r1)
- bbox->y1 = p1.y + r1;
- return bbox;
-}
-
-static fz_rect *
-fz_bound_mesh_type4567(fz_context *ctx, fz_shade *shade, fz_rect *bbox)
-{
- bbox->x0 = shade->u.m.x0;
- bbox->y0 = shade->u.m.y0;
- bbox->x1 = shade->u.m.x1;
- bbox->y1 = shade->u.m.y1;
- return bbox;
-}
-
-static fz_rect *
-fz_bound_mesh(fz_context *ctx, fz_shade *shade, fz_rect *bbox)
-{
- if (shade->type == FZ_FUNCTION_BASED)
- fz_bound_mesh_type1(ctx, shade, bbox);
- else if (shade->type == FZ_LINEAR)
- fz_bound_mesh_type2(ctx, shade, bbox);
- else if (shade->type == FZ_RADIAL)
- fz_bound_mesh_type3(ctx, shade, bbox);
- else if (shade->type == FZ_MESH_TYPE4 ||
- shade->type == FZ_MESH_TYPE5 ||
- shade->type == FZ_MESH_TYPE6 ||
- shade->type == FZ_MESH_TYPE7)
- fz_bound_mesh_type4567(ctx, shade, bbox);
- else
- fz_throw(ctx, FZ_ERROR_GENERIC, "Unexpected mesh type %d\n", shade->type);
-
- return bbox;
-}
-
-fz_shade *
-fz_keep_shade(fz_context *ctx, fz_shade *shade)
-{
- return (fz_shade *)fz_keep_storable(ctx, &shade->storable);
-}
-
-void
-fz_free_shade_imp(fz_context *ctx, fz_storable *shade_)
-{
- fz_shade *shade = (fz_shade *)shade_;
-
- if (shade->colorspace)
- fz_drop_colorspace(ctx, shade->colorspace);
- if (shade->type == FZ_FUNCTION_BASED)
- fz_free(ctx, shade->u.f.fn_vals);
- fz_free_compressed_buffer(ctx, shade->buffer);
- fz_free(ctx, shade);
-}
-
-void
-fz_drop_shade(fz_context *ctx, fz_shade *shade)
-{
- fz_drop_storable(ctx, &shade->storable);
-}
-
-fz_rect *
-fz_bound_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_rect *s)
-{
- fz_matrix local_ctm;
- fz_rect rect;
-
- fz_concat(&local_ctm, &shade->matrix, ctm);
- *s = shade->bbox;
- if (shade->type != FZ_LINEAR && shade->type != FZ_RADIAL)
- {
- fz_bound_mesh(ctx, shade, &rect);
- fz_intersect_rect(s, &rect);
- }
- return fz_transform_rect(s, &local_ctm);
-}
-
-#ifndef NDEBUG
-void
-fz_print_shade(fz_context *ctx, FILE *out, fz_shade *shade)
-{
- int i;
-
- fprintf(out, "shading {\n");
-
- switch (shade->type)
- {
- case FZ_FUNCTION_BASED: fprintf(out, "\ttype function_based\n"); break;
- case FZ_LINEAR: fprintf(out, "\ttype linear\n"); break;
- case FZ_RADIAL: fprintf(out, "\ttype radial\n"); break;
- default: /* MESH */ fprintf(out, "\ttype mesh\n"); break;
- }
-
- fprintf(out, "\tbbox [%g %g %g %g]\n",
- shade->bbox.x0, shade->bbox.y0,
- shade->bbox.x1, shade->bbox.y1);
-
- fprintf(out, "\tcolorspace %s\n", shade->colorspace->name);
-
- 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)
- {
- fprintf(out, "\tbackground [");
- for (i = 0; i < shade->colorspace->n; i++)
- fprintf(out, "%s%g", i == 0 ? "" : " ", shade->background[i]);
- fprintf(out, "]\n");
- }
-
- if (shade->use_function)
- {
- fprintf(out, "\tfunction\n");
- }
-
- fprintf(out, "}\n");
-}
-#endif
diff --git a/fitz/res_store.c b/fitz/res_store.c
deleted file mode 100644
index 609f10dc..00000000
--- a/fitz/res_store.c
+++ /dev/null
@@ -1,638 +0,0 @@
-#include "mupdf/fitz.h"
-
-typedef struct fz_item_s fz_item;
-
-struct fz_item_s
-{
- void *key;
- fz_storable *val;
- unsigned int size;
- fz_item *next;
- fz_item *prev;
- fz_store *store;
- fz_store_type *type;
-};
-
-struct fz_store_s
-{
- int refs;
-
- /* Every item in the store is kept in a doubly linked list, ordered
- * by usage (so LRU entries are at the end). */
- fz_item *head;
- fz_item *tail;
-
- /* We have a hash table that allows to quickly find a subset of the
- * entries (those whose keys are indirect objects). */
- fz_hash_table *hash;
-
- /* We keep track of the size of the store, and keep it below max. */
- unsigned int max;
- unsigned int size;
-};
-
-void
-fz_new_store_context(fz_context *ctx, unsigned int max)
-{
- fz_store *store;
- store = fz_malloc_struct(ctx, fz_store);
- fz_try(ctx)
- {
- store->hash = fz_new_hash_table(ctx, 4096, sizeof(fz_store_hash), FZ_LOCK_ALLOC);
- }
- fz_catch(ctx)
- {
- fz_free(ctx, store);
- fz_rethrow(ctx);
- }
- store->refs = 1;
- store->head = NULL;
- store->tail = NULL;
- store->size = 0;
- store->max = max;
- ctx->store = store;
-}
-
-void *
-fz_keep_storable(fz_context *ctx, fz_storable *s)
-{
- if (s == NULL)
- return NULL;
- fz_lock(ctx, FZ_LOCK_ALLOC);
- if (s->refs > 0)
- s->refs++;
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- return s;
-}
-
-void
-fz_drop_storable(fz_context *ctx, fz_storable *s)
-{
- int do_free = 0;
-
- if (s == NULL)
- return;
- fz_lock(ctx, FZ_LOCK_ALLOC);
- if (s->refs < 0)
- {
- /* It's a static object. Dropping does nothing. */
- }
- else if (--s->refs == 0)
- {
- /* If we are dropping the last reference to an object, then
- * it cannot possibly be in the store (as the store always
- * keeps a ref to everything in it, and doesn't drop via
- * this method. So we can simply drop the storable object
- * itself without any operations on the fz_store. */
- do_free = 1;
- }
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- if (do_free)
- s->free(ctx, s);
-}
-
-static void
-evict(fz_context *ctx, fz_item *item)
-{
- fz_store *store = ctx->store;
- int drop;
-
- store->size -= item->size;
- /* Unlink from the linked list */
- if (item->next)
- item->next->prev = item->prev;
- else
- store->tail = item->prev;
- if (item->prev)
- item->prev->next = item->next;
- else
- store->head = item->next;
- /* Drop a reference to the value (freeing if required) */
- drop = (item->val->refs > 0 && --item->val->refs == 0);
- /* Remove from the hash table */
- if (item->type->make_hash_key)
- {
- 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 */
- item->type->drop_key(ctx, item->key);
- fz_free(ctx, item);
- fz_lock(ctx, FZ_LOCK_ALLOC);
-}
-
-static int
-ensure_space(fz_context *ctx, unsigned int tofree)
-{
- fz_item *item, *prev;
- unsigned int count;
- fz_store *store = ctx->store;
-
- fz_assert_lock_held(ctx, FZ_LOCK_ALLOC);
-
- /* First check that we *can* free tofree; if not, we'd rather not
- * cache this. */
- count = 0;
- for (item = store->tail; item; item = item->prev)
- {
- if (item->val->refs == 1)
- {
- count += item->size;
- if (count >= tofree)
- break;
- }
- }
-
- /* If we ran out of items to search, then we can never free enough */
- if (item == NULL)
- {
- return 0;
- }
-
- /* Actually free the items */
- count = 0;
- for (item = store->tail; item; item = prev)
- {
- prev = item->prev;
- if (item->val->refs == 1)
- {
- /* Free this item. Evict has to drop the lock to
- * manage that, which could cause prev to be removed
- * in the meantime. To avoid that we bump its reference
- * count here. This may cause another simultaneous
- * evict process to fail to make enough space as prev is
- * pinned - but that will only happen if we're near to
- * the limit anyway, and it will only cause something to
- * not be cached. */
- count += item->size;
- if (prev)
- prev->val->refs++;
- evict(ctx, item); /* Drops then retakes lock */
- /* So the store has 1 reference to prev, as do we, so
- * no other evict process can have thrown prev away in
- * the meantime. So we are safe to just decrement its
- * reference count here. */
- if (prev)
- --prev->val->refs;
-
- if (count >= tofree)
- return count;
- }
- }
-
- return count;
-}
-
-static void
-touch(fz_store *store, fz_item *item)
-{
- if (item->next != item)
- {
- /* Already in the list - unlink it */
- if (item->next)
- item->next->prev = item->prev;
- else
- store->tail = item->prev;
- if (item->prev)
- item->prev->next = item->next;
- else
- store->head = item->next;
- }
- /* Now relink it at the start of the LRU chain */
- item->next = store->head;
- if (item->next)
- item->next->prev = item;
- else
- store->tail = item;
- store->head = item;
- item->prev = NULL;
-}
-
-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;
- fz_store_hash hash = { NULL };
- int use_hash = 0;
- unsigned pos;
-
- if (!store)
- return NULL;
-
- fz_var(item);
-
- if (store->max != FZ_STORE_UNLIMITED && store->max < itemsize)
- {
- /* Our item would take up more room than we can ever
- * possibly have in the store. Just give up now. */
- return NULL;
- }
-
- /* 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. */
- fz_try(ctx)
- {
- item = fz_malloc_struct(ctx, fz_item);
- }
- fz_catch(ctx)
- {
- 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);
-
- /* Fill out the item. To start with, we always set item->next == item
- * and item->prev == item. This is so that we can spot items that have
- * been put into the hash table without having made it into the linked
- * list yet. */
- item->key = key;
- item->val = val;
- item->size = itemsize;
- item->next = item;
- item->prev = item;
- item->type = type;
-
- /* If we can index it fast, put it into the hash table. This serves
- * to check whether we have one there already. */
- if (use_hash)
- {
- fz_item *existing;
-
- fz_try(ctx)
- {
- /* May drop and retake the lock */
- existing = fz_hash_insert_with_pos(ctx, store->hash, &hash, item, &pos);
- }
- fz_catch(ctx)
- {
- /* Any error here means that item never made it into the
- * hash - so no one else can have a reference. */
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- fz_free(ctx, item);
- type->drop_key(ctx, key);
- return NULL;
- }
- if (existing)
- {
- /* There was one there already! Take a new reference
- * to the existing one, and drop our current one. */
- touch(store, existing);
- if (existing->val->refs > 0)
- existing->val->refs++;
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- fz_free(ctx, item);
- type->drop_key(ctx, key);
- return existing->val;
- }
- }
- /* Now bump the ref */
- if (val->refs > 0)
- val->refs++;
- /* If we haven't got an infinite store, check for space within it */
- if (store->max != FZ_STORE_UNLIMITED)
- {
- size = store->size + itemsize;
- while (size > store->max)
- {
- /* ensure_space may drop, then retake the lock */
- int saved = ensure_space(ctx, size - store->max);
- if (saved == 0)
- {
- /* Failed to free any space. */
- /* If we are using the hash table, then we've already
- * inserted item - remove it. */
- if (use_hash)
- {
- /* If someone else has already picked up a reference
- * to item, then we cannot remove it. Leave it in the
- * store, and we'll live with being over budget. We
- * know this is the case, if it's in the linked list. */
- if (item->next != item)
- break;
- fz_hash_remove_fast(ctx, store->hash, &hash, pos);
- }
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- fz_free(ctx, item);
- type->drop_key(ctx, key);
- if (val->refs > 0)
- val->refs--;
- return NULL;
- }
- size -= saved;
- }
- }
- store->size += itemsize;
-
- /* Regardless of whether it's indexed, it goes into the linked list */
- touch(store, item);
- fz_unlock(ctx, FZ_LOCK_ALLOC);
-
- return NULL;
-}
-
-void *
-fz_find_item(fz_context *ctx, fz_store_free_fn *free, void *key, fz_store_type *type)
-{
- fz_item *item;
- fz_store *store = ctx->store;
- fz_store_hash hash = { NULL };
- int use_hash = 0;
-
- if (!store)
- return NULL;
-
- if (!key)
- return NULL;
-
- if (type->make_hash_key)
- {
- hash.free = free;
- use_hash = type->make_hash_key(&hash, key);
- }
-
- fz_lock(ctx, FZ_LOCK_ALLOC);
- if (use_hash)
- {
- /* We can find objects keyed on indirected objects quickly */
- 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 && !type->cmp_key(item->key, key))
- break;
- }
- }
- if (item)
- {
- /* LRU the block. This also serves to ensure that any item
- * picked up from the hash before it has made it into the
- * linked list does not get whipped out again due to the
- * store being full. */
- touch(store, item);
- /* And bump the refcount before returning */
- if (item->val->refs > 0)
- item->val->refs++;
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- return (void *)item->val;
- }
- fz_unlock(ctx, FZ_LOCK_ALLOC);
-
- return NULL;
-}
-
-void
-fz_remove_item(fz_context *ctx, fz_store_free_fn *free, void *key, fz_store_type *type)
-{
- fz_item *item;
- fz_store *store = ctx->store;
- int drop;
- fz_store_hash hash = { NULL };
- int use_hash = 0;
-
- if (type->make_hash_key)
- {
- hash.free = free;
- use_hash = type->make_hash_key(&hash, key);
- }
-
- fz_lock(ctx, FZ_LOCK_ALLOC);
- if (use_hash)
- {
- /* We can find objects keyed on indirect objects quickly */
- item = fz_hash_find(ctx, store->hash, &hash);
- if (item)
- 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 && !type->cmp_key(item->key, key))
- break;
- }
- if (item)
- {
- /* Momentarily things can be in the hash table without being
- * in the list. Don't attempt to unlink these. We indicate
- * such items by setting item->next == item. */
- if (item->next != item)
- {
- if (item->next)
- item->next->prev = item->prev;
- else
- store->tail = item->prev;
- if (item->prev)
- item->prev->next = item->next;
- else
- store->head = item->next;
- }
- drop = (item->val->refs > 0 && --item->val->refs == 0);
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- if (drop)
- item->val->free(ctx, item->val);
- type->drop_key(ctx, item->key);
- fz_free(ctx, item);
- }
- else
- fz_unlock(ctx, FZ_LOCK_ALLOC);
-}
-
-void
-fz_empty_store(fz_context *ctx)
-{
- fz_store *store = ctx->store;
-
- if (store == NULL)
- return;
-
- fz_lock(ctx, FZ_LOCK_ALLOC);
- /* Run through all the items in the store */
- while (store->head)
- {
- evict(ctx, store->head); /* Drops then retakes lock */
- }
- fz_unlock(ctx, FZ_LOCK_ALLOC);
-}
-
-fz_store *
-fz_keep_store_context(fz_context *ctx)
-{
- if (ctx == NULL || ctx->store == NULL)
- return NULL;
- fz_lock(ctx, FZ_LOCK_ALLOC);
- ctx->store->refs++;
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- return ctx->store;
-}
-
-void
-fz_drop_store_context(fz_context *ctx)
-{
- int refs;
- if (ctx == NULL || ctx->store == NULL)
- return;
- fz_lock(ctx, FZ_LOCK_ALLOC);
- refs = --ctx->store->refs;
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- if (refs != 0)
- return;
-
- fz_empty_store(ctx);
- fz_free_hash(ctx, ctx->store->hash);
- fz_free(ctx, ctx->store);
- ctx->store = NULL;
-}
-
-#ifndef NDEBUG
-static void
-print_item(FILE *out, void *item_)
-{
- fz_item *item = (fz_item *)item_;
- fprintf(out, " val=%p item=%p\n", item->val, item);
- fflush(out);
-}
-
-void
-fz_print_store_locked(fz_context *ctx, FILE *out)
-{
- fz_item *item, *next;
- fz_store *store = ctx->store;
-
- fprintf(out, "-- resource store contents --\n");
- fflush(out);
-
- for (item = store->head; item; item = next)
- {
- next = item->next;
- if (next)
- next->val->refs++;
- fprintf(out, "store[*][refs=%d][size=%d] ", item->val->refs, item->size);
- fz_unlock(ctx, FZ_LOCK_ALLOC);
- item->type->debug(out, item->key);
- fprintf(out, " = %p\n", item->val);
- fflush(out);
- fz_lock(ctx, FZ_LOCK_ALLOC);
- if (next)
- next->val->refs--;
- }
- fprintf(out, "-- resource store hash contents --\n");
- fz_print_hash_details(ctx, out, store->hash, print_item);
- fprintf(out, "-- end --\n");
- fflush(out);
-}
-
-void
-fz_print_store(fz_context *ctx, FILE *out)
-{
- fz_lock(ctx, FZ_LOCK_ALLOC);
- fz_print_store_locked(ctx, out);
- fz_unlock(ctx, FZ_LOCK_ALLOC);
-}
-#endif
-
-/* This is now an n^2 algorithm - not ideal, but it'll only be bad if we are
- * actually managing to scavenge lots of blocks back. */
-static int
-scavenge(fz_context *ctx, unsigned int tofree)
-{
- fz_store *store = ctx->store;
- unsigned int count = 0;
- fz_item *item, *prev;
-
- /* Free the items */
- for (item = store->tail; item; item = prev)
- {
- prev = item->prev;
- if (item->val->refs == 1)
- {
- /* Free this item */
- count += item->size;
- evict(ctx, item); /* Drops then retakes lock */
-
- if (count >= tofree)
- break;
-
- /* Have to restart search again, as prev may no longer
- * be valid due to release of lock in evict. */
- prev = store->tail;
- }
- }
- /* Success is managing to evict any blocks */
- return count != 0;
-}
-
-int fz_store_scavenge(fz_context *ctx, unsigned int size, int *phase)
-{
- fz_store *store;
- unsigned int max;
-
- if (ctx == NULL)
- return 0;
- store = ctx->store;
- if (store == NULL)
- return 0;
-
-#ifdef DEBUG_SCAVENGING
- printf("Scavenging: store=%d size=%d phase=%d\n", store->size, size, *phase);
- fz_print_store_locked(ctx, stderr);
- Memento_stats();
-#endif
- do
- {
- unsigned int tofree;
-
- /* Calculate 'max' as the maximum size of the store for this phase */
- if (*phase >= 16)
- max = 0;
- else if (store->max != FZ_STORE_UNLIMITED)
- max = store->max / 16 * (16 - *phase);
- else
- max = store->size / (16 - *phase) * (15 - *phase);
- (*phase)++;
-
- /* Slightly baroque calculations to avoid overflow */
- if (size > UINT_MAX - store->size)
- tofree = UINT_MAX - max;
- else if (size + store->size > max)
- continue;
- else
- tofree = size + store->size - max;
-
- if (scavenge(ctx, tofree))
- {
-#ifdef DEBUG_SCAVENGING
- printf("scavenged: store=%d\n", store->size);
- fz_print_store(ctx, stderr);
- Memento_stats();
-#endif
- return 1;
- }
- }
- while (max > 0);
-
-#ifdef DEBUG_SCAVENGING
- printf("scavenging failed\n");
- fz_print_store(ctx, stderr);
- Memento_listBlocks();
-#endif
- return 0;
-}
diff --git a/fitz/res_text.c b/fitz/res_text.c
deleted file mode 100644
index 81e2e1d0..00000000
--- a/fitz/res_text.c
+++ /dev/null
@@ -1,154 +0,0 @@
-#include "mupdf/fitz.h"
-
-fz_text *
-fz_new_text(fz_context *ctx, fz_font *font, const fz_matrix *trm, int wmode)
-{
- fz_text *text;
-
- text = fz_malloc_struct(ctx, fz_text);
- text->font = fz_keep_font(ctx, font);
- text->trm = *trm;
- text->wmode = wmode;
- text->len = 0;
- text->cap = 0;
- text->items = NULL;
-
- return text;
-}
-
-void
-fz_free_text(fz_context *ctx, fz_text *text)
-{
- if (text != NULL)
- {
- fz_drop_font(ctx, text->font);
- fz_free(ctx, text->items);
- }
- fz_free(ctx, text);
-}
-
-fz_text *
-fz_clone_text(fz_context *ctx, fz_text *old)
-{
- fz_text *text;
-
- text = fz_malloc_struct(ctx, fz_text);
- text->len = old->len;
- fz_try(ctx)
- {
- text->items = fz_malloc_array(ctx, text->len, sizeof(fz_text_item));
- }
- fz_catch(ctx)
- {
- fz_free(ctx, text);
- fz_rethrow(ctx);
- }
- memcpy(text->items, old->items, text->len * sizeof(fz_text_item));
- text->font = fz_keep_font(ctx, old->font);
- text->trm = old->trm;
- text->wmode = old->wmode;
- text->cap = text->len;
-
- return text;
-}
-
-fz_rect *
-fz_bound_text(fz_context *ctx, fz_text *text, const fz_stroke_state *stroke, const fz_matrix *ctm, fz_rect *bbox)
-{
- fz_matrix tm, trm;
- fz_rect gbox;
- int i;
-
- if (text->len == 0)
- {
- *bbox = fz_empty_rect;
- return bbox;
- }
-
- // TODO: stroke state
-
- tm = text->trm;
-
- tm.e = text->items[0].x;
- tm.f = text->items[0].y;
- fz_concat(&trm, &tm, ctm);
- fz_bound_glyph(ctx, text->font, text->items[0].gid, &trm, bbox);
-
- for (i = 1; i < text->len; i++)
- {
- if (text->items[i].gid >= 0)
- {
- tm.e = text->items[i].x;
- tm.f = text->items[i].y;
- fz_concat(&trm, &tm, ctm);
- fz_bound_glyph(ctx, text->font, text->items[i].gid, &trm, &gbox);
-
- bbox->x0 = fz_min(bbox->x0, gbox.x0);
- bbox->y0 = fz_min(bbox->y0, gbox.y0);
- bbox->x1 = fz_max(bbox->x1, gbox.x1);
- bbox->y1 = fz_max(bbox->y1, gbox.y1);
- }
- }
-
- if (stroke)
- fz_adjust_rect_for_stroke(bbox, stroke, ctm);
-
- /* Compensate for the glyph cache limited positioning precision */
- bbox->x0 -= 1;
- bbox->y0 -= 1;
- bbox->x1 += 1;
- bbox->y1 += 1;
-
- return bbox;
-}
-
-static void
-fz_grow_text(fz_context *ctx, fz_text *text, int n)
-{
- int new_cap = text->cap;
- if (text->len + n < new_cap)
- return;
- while (text->len + n > new_cap)
- new_cap = new_cap + 36;
- text->items = fz_resize_array(ctx, text->items, new_cap, sizeof(fz_text_item));
- text->cap = new_cap;
-}
-
-void
-fz_add_text(fz_context *ctx, fz_text *text, int gid, int ucs, float x, float y)
-{
- fz_grow_text(ctx, text, 1);
- text->items[text->len].ucs = ucs;
- text->items[text->len].gid = gid;
- text->items[text->len].x = x;
- text->items[text->len].y = y;
- text->len++;
-}
-
-static int
-isxmlmeta(int c)
-{
- return c < 32 || c >= 128 || c == '&' || c == '<' || c == '>' || c == '\'' || c == '"';
-}
-
-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++)
- fputc(' ', out);
- if (!isxmlmeta(text->items[i].ucs))
- fprintf(out, "<g ucs=\"%c\" gid=\"%d\" x=\"%g\" y=\"%g\" />\n",
- text->items[i].ucs, text->items[i].gid, text->items[i].x, text->items[i].y);
- else
- fprintf(out, "<g ucs=\"U+%04X\" gid=\"%d\" x=\"%g\" y=\"%g\" />\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);
-}
diff --git a/fitz/stm_buffer.c b/fitz/stm_buffer.c
deleted file mode 100644
index 388e0461..00000000
--- a/fitz/stm_buffer.c
+++ /dev/null
@@ -1,390 +0,0 @@
-#include "mupdf/fitz.h"
-
-fz_buffer *
-fz_new_buffer(fz_context *ctx, int size)
-{
- fz_buffer *b;
-
- size = size > 1 ? size : 16;
-
- b = fz_malloc_struct(ctx, fz_buffer);
- b->refs = 1;
- fz_try(ctx)
- {
- b->data = fz_malloc(ctx, size);
- }
- fz_catch(ctx)
- {
- fz_free(ctx, b);
- fz_rethrow(ctx);
- }
- b->cap = size;
- b->len = 0;
- b->unused_bits = 0;
-
- return b;
-}
-
-fz_buffer *
-fz_new_buffer_from_data(fz_context *ctx, unsigned char *data, int size)
-{
- fz_buffer *b;
-
- b = fz_malloc_struct(ctx, fz_buffer);
- b->refs = 1;
- b->data = data;
- b->cap = size;
- b->len = size;
- b->unused_bits = 0;
-
- return b;
-}
-
-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;
-}
-
-void
-fz_drop_buffer(fz_context *ctx, fz_buffer *buf)
-{
- if (!buf)
- return;
- if (--buf->refs == 0)
- {
- fz_free(ctx, buf->data);
- fz_free(ctx, buf);
- }
-}
-
-void
-fz_resize_buffer(fz_context *ctx, fz_buffer *buf, int size)
-{
- buf->data = fz_resize_array(ctx, buf->data, size, 1);
- buf->cap = size;
- if (buf->len > buf->cap)
- buf->len = buf->cap;
-}
-
-void
-fz_grow_buffer(fz_context *ctx, fz_buffer *buf)
-{
- int newsize = (buf->cap * 3) / 2;
- if (newsize == 0)
- newsize = 256;
- fz_resize_buffer(ctx, buf, newsize);
-}
-
-static void
-fz_ensure_buffer(fz_context *ctx, fz_buffer *buf, int min)
-{
- int newsize = buf->cap;
- while (newsize < min)
- {
- newsize = (newsize * 3) / 2;
- }
- fz_resize_buffer(ctx, buf, newsize);
-}
-
-void
-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);
-}
-
-void
-fz_buffer_cat(fz_context *ctx, fz_buffer *buf, fz_buffer *extra)
-{
- if (buf->cap - buf->len < extra->len)
- {
- buf->data = fz_resize_array(ctx, buf->data, buf->len + extra->len, 1);
- buf->cap = buf->len + extra->len;
- }
-
- memcpy(buf->data + buf->len, extra->data, extra->len);
- buf->len += extra->len;
-}
-
-void fz_write_buffer(fz_context *ctx, fz_buffer *buf, const void *data, int len)
-{
- if (buf->len + len > buf->cap)
- fz_ensure_buffer(ctx, buf, buf->len + len);
- memcpy(buf->data + buf->len, data, len);
- buf->len += len;
- buf->unused_bits = 0;
-}
-
-void fz_write_buffer_byte(fz_context *ctx, fz_buffer *buf, int val)
-{
- if (buf->len > buf->cap)
- fz_grow_buffer(ctx, buf);
- buf->data[buf->len++] = val;
- buf->unused_bits = 0;
-}
-
-void fz_write_buffer_rune(fz_context *ctx, fz_buffer *buf, int c)
-{
- char data[10];
- int len = fz_runetochar(data, c);
- if (buf->len + len > buf->cap)
- fz_ensure_buffer(ctx, buf, buf->len + len);
- memcpy(buf->data + buf->len, data, len);
- buf->len += len;
- buf->unused_bits = 0;
-}
-
-void fz_write_buffer_bits(fz_context *ctx, fz_buffer *buf, int val, int bits)
-{
- int shift;
-
- /* Throughout this code, the invariant is that we need to write the
- * bottom 'bits' bits of 'val' into the stream. On entry we assume
- * that val & ((1<<bits)-1) == val, but we do not rely on this after
- * having written the first partial byte. */
-
- if (bits == 0)
- return;
-
- /* buf->len always covers all the bits in the buffer, including
- * any unused ones in the last byte, which will always be 0.
- * buf->unused_bits = the number of unused bits in the last byte.
- */
-
- /* Find the amount we need to shift val up by so that it will be in
- * the correct position to be inserted into any existing data byte. */
- shift = (buf->unused_bits - bits);
-
- /* Extend the buffer as required before we start; that way we never
- * fail part way during writing. If shift < 0, then we'll need -shift
- * more bits. */
- if (shift < 0)
- {
- int extra = (7-shift)>>3; /* Round up to bytes */
- fz_ensure_buffer(ctx, buf, buf->len + extra);
- }
-
- /* Write any bits that will fit into the existing byte */
- if (buf->unused_bits)
- {
- buf->data[buf->len-1] |= (shift >= 0 ? (((unsigned int)val)<<shift) : (((unsigned int)val)>>-shift));
- if (shift >= 0)
- {
- /* If we were shifting up, we're done. */
- buf->unused_bits -= bits;
- return;
- }
- /* The number of bits left to write is the number that didn't
- * fit in this first byte. */
- bits = -shift;
- }
-
- /* Write any whole bytes */
- while (bits >= 8)
- {
- bits -= 8;
- buf->data[buf->len++] = val>>bits;
- }
-
- /* Write trailing bits (with 0's in unused bits) */
- if (bits > 0)
- {
- bits = 8-bits;
- buf->data[buf->len++] = val<<bits;
- }
- buf->unused_bits = bits;
-}
-
-void fz_write_buffer_pad(fz_context *ctx, fz_buffer *buf)
-{
- buf->unused_bits = 0;
-}
-
-int
-fz_buffer_printf(fz_context *ctx, fz_buffer *buffer, const char *fmt, ...)
-{
- int ret;
- va_list args;
- va_start(args, fmt);
-
- ret = fz_buffer_vprintf(ctx, buffer, fmt, args);
-
- va_end(args);
-
- return ret;
-}
-
-int
-fz_buffer_vprintf(fz_context *ctx, fz_buffer *buffer, const char *fmt, va_list old_args)
-{
- int len;
-
- do
- {
- int slack = buffer->cap - buffer->len;
-
- if (slack > 0)
- {
- va_list args;
-#ifdef _MSC_VER /* Microsoft Visual C */
- args = old_args;
-#else
- va_copy(args, old_args);
-#endif
- len = vsnprintf((char *)buffer->data + buffer->len, slack, fmt, args);
-#ifndef _MSC_VER
- va_end(args);
-#endif
- /* len = number of chars written, not including the terminating
- * NULL, so len+1 > slack means "truncated". MSVC differs here
- * and returns -1 for truncated. */
- if (len >= 0 && len+1 <= slack)
- break;
- }
- /* Grow the buffer and retry */
- fz_grow_buffer(ctx, buffer);
- }
- while (1);
-
- buffer->len += len;
-
- return len;
-}
-
-void
-fz_buffer_cat_pdf_string(fz_context *ctx, fz_buffer *buffer, const char *text)
-{
- int len = 2;
- const char *s = text;
- char *d;
- char c;
-
- while ((c = *s++) != 0)
- {
- switch (c)
- {
- case '\n':
- case '\r':
- case '\t':
- case '\b':
- case '\f':
- case '(':
- case ')':
- case '\\':
- len++;
- break;
- }
- len++;
- }
-
- while(buffer->cap - buffer->len < len)
- fz_grow_buffer(ctx, buffer);
-
- s = text;
- d = (char *)buffer->data + buffer->len;
- *d++ = '(';
- while ((c = *s++) != 0)
- {
- switch (c)
- {
- case '\n':
- *d++ = '\\';
- *d++ = 'n';
- break;
- case '\r':
- *d++ = '\\';
- *d++ = 'r';
- break;
- case '\t':
- *d++ = '\\';
- *d++ = 't';
- break;
- case '\b':
- *d++ = '\\';
- *d++ = 'b';
- break;
- case '\f':
- *d++ = '\\';
- *d++ = 'f';
- break;
- case '(':
- *d++ = '\\';
- *d++ = '(';
- break;
- case ')':
- *d++ = '\\';
- *d++ = ')';
- break;
- case '\\':
- *d++ = '\\';
- *d++ = '\\';
- break;
- default:
- *d++ = c;
- }
- }
- *d++ = ')';
- buffer->len += len;
-}
-
-#ifdef TEST_BUFFER_WRITE
-
-#define TEST_LEN 1024
-
-void
-fz_test_buffer_write(fz_context *ctx)
-{
- fz_buffer *master = fz_new_buffer(ctx, TEST_LEN);
- fz_buffer *copy = fz_new_buffer(ctx, TEST_LEN);
- fz_stream *stm;
- int i, j, k;
-
- /* Make us a dummy buffer */
- for (i = 0; i < TEST_LEN; i++)
- {
- master->data[i] = rand();
- }
- master->len = TEST_LEN;
-
- /* Now copy that buffer several times, checking it for validity */
- stm = fz_open_buffer(ctx, master);
- for (i = 0; i < 256; i++)
- {
- memset(copy->data, i, TEST_LEN);
- copy->len = 0;
- j = TEST_LEN * 8;
- do
- {
- k = (rand() & 31)+1;
- if (k > j)
- k = j;
- fz_write_buffer_bits(ctx, copy, fz_read_bits(stm, k), k);
- j -= k;
- }
- while (j);
-
- if (memcmp(copy->data, master->data, TEST_LEN) != 0)
- fprintf(stderr, "Copied buffer is different!\n");
- fz_seek(stm, 0, 0);
- }
- fz_close(stm);
- fz_drop_buffer(ctx, master);
- fz_drop_buffer(ctx, copy);
-}
-#endif
diff --git a/fitz/stm_comp_buf.c b/fitz/stm_comp_buf.c
deleted file mode 100644
index acdf2747..00000000
--- a/fitz/stm_comp_buf.c
+++ /dev/null
@@ -1,75 +0,0 @@
-#include "mupdf/fitz.h"
-
-/* This code needs to be kept out of stm_buffer.c to avoid it being
- * pulled into cmapdump.c */
-
-void
-fz_free_compressed_buffer(fz_context *ctx, fz_compressed_buffer *buf)
-{
- if (!buf)
- return;
-
- fz_drop_buffer(ctx, buf->buffer);
- fz_free(ctx, buf);
-}
-
-fz_stream *
-fz_open_image_decomp_stream(fz_context *ctx, fz_compressed_buffer *buffer, int *l2factor)
-{
- fz_stream *chain = fz_open_buffer(ctx, buffer->buffer);
- fz_compression_params *params = &buffer->params;
-
- switch (params->type)
- {
- case FZ_IMAGE_FAX:
- *l2factor = 0;
- return fz_open_faxd(chain,
- params->u.fax.k,
- params->u.fax.end_of_line,
- params->u.fax.encoded_byte_align,
- params->u.fax.columns,
- params->u.fax.rows,
- params->u.fax.end_of_block,
- params->u.fax.black_is_1);
- case FZ_IMAGE_JPEG:
- if (*l2factor > 3)
- *l2factor = 3;
- return fz_open_resized_dctd(chain, params->u.jpeg.color_transform, *l2factor);
- case FZ_IMAGE_RLD:
- *l2factor = 0;
- return fz_open_rld(chain);
- case FZ_IMAGE_FLATE:
- *l2factor = 0;
- chain = fz_open_flated(chain);
- if (params->u.flate.predictor > 1)
- chain = fz_open_predict(chain, params->u.flate.predictor, params->u.flate.columns, params->u.flate.colors, params->u.flate.bpc);
- return chain;
- case FZ_IMAGE_LZW:
- *l2factor = 0;
- chain = fz_open_lzwd(chain, params->u.lzw.early_change);
- if (params->u.lzw.predictor > 1)
- chain = fz_open_predict(chain, params->u.lzw.predictor, params->u.lzw.columns, params->u.lzw.colors, params->u.lzw.bpc);
- return chain;
- default:
- *l2factor = 0;
- break;
- }
-
- return chain;
-}
-
-fz_stream *
-fz_open_compressed_buffer(fz_context *ctx, fz_compressed_buffer *buffer)
-{
- int l2factor = 0;
-
- return fz_open_image_decomp_stream(ctx, buffer, &l2factor);
-}
-
-unsigned int
-fz_compressed_buffer_size(fz_compressed_buffer *buffer)
-{
- if (!buffer || !buffer->buffer)
- return 0;
- return (unsigned int)buffer->buffer->cap;
-}
diff --git a/fitz/stm_open.c b/fitz/stm_open.c
deleted file mode 100644
index 9e4dc8d4..00000000
--- a/fitz/stm_open.c
+++ /dev/null
@@ -1,210 +0,0 @@
-#include "mupdf/fitz.h"
-
-fz_stream *
-fz_new_stream(fz_context *ctx, void *state,
- int(*read)(fz_stream *stm, unsigned char *buf, int len),
- void(*close)(fz_context *ctx, void *state))
-{
- fz_stream *stm;
-
- fz_try(ctx)
- {
- stm = fz_malloc_struct(ctx, fz_stream);
- }
- fz_catch(ctx)
- {
- close(ctx, state);
- fz_rethrow(ctx);
- }
-
- stm->refs = 1;
- stm->error = 0;
- stm->eof = 0;
- stm->pos = 0;
-
- stm->bits = 0;
- stm->avail = 0;
-
- stm->bp = stm->buf;
- stm->rp = stm->bp;
- stm->wp = stm->bp;
- stm->ep = stm->buf + sizeof stm->buf;
-
- stm->state = state;
- stm->read = read;
- stm->close = close;
- stm->seek = NULL;
- stm->ctx = ctx;
-
- return stm;
-}
-
-fz_stream *
-fz_keep_stream(fz_stream *stm)
-{
- if (stm)
- stm->refs ++;
- return stm;
-}
-
-void
-fz_close(fz_stream *stm)
-{
- if (!stm)
- return;
- stm->refs --;
- if (stm->refs == 0)
- {
- if (stm->close)
- stm->close(stm->ctx, stm->state);
- fz_free(stm->ctx, stm);
- }
-}
-
-/* File stream */
-
-static int read_file(fz_stream *stm, unsigned char *buf, int len)
-{
- int n = read(*(int*)stm->state, buf, len);
- if (n < 0)
- fz_throw(stm->ctx, FZ_ERROR_GENERIC, "read error: %s", strerror(errno));
- return n;
-}
-
-static void seek_file(fz_stream *stm, int offset, int whence)
-{
- int n = lseek(*(int*)stm->state, offset, whence);
- if (n < 0)
- fz_throw(stm->ctx, FZ_ERROR_GENERIC, "cannot lseek: %s", strerror(errno));
- stm->pos = n;
- stm->rp = stm->bp;
- stm->wp = stm->bp;
-}
-
-static void close_file(fz_context *ctx, void *state)
-{
- int n = close(*(int*)state);
- if (n < 0)
- fz_warn(ctx, "close error: %s", strerror(errno));
- fz_free(ctx, state);
-}
-
-fz_stream *
-fz_open_fd(fz_context *ctx, int fd)
-{
- fz_stream *stm;
- int *state;
-
- state = fz_malloc_struct(ctx, int);
- *state = fd;
-
- fz_try(ctx)
- {
- stm = fz_new_stream(ctx, state, read_file, close_file);
- }
- fz_catch(ctx)
- {
- fz_free(ctx, state);
- fz_rethrow(ctx);
- }
- stm->seek = seek_file;
-
- return stm;
-}
-
-fz_stream *
-fz_open_file(fz_context *ctx, const char *name)
-{
-#ifdef _WIN32
- char *s = (char*)name;
- wchar_t *wname, *d;
- int c, fd;
- d = wname = fz_malloc(ctx, (strlen(name)+1) * sizeof(wchar_t));
- while (*s) {
- s += fz_chartorune(&c, s);
- *d++ = c;
- }
- *d = 0;
- fd = _wopen(wname, O_BINARY | O_RDONLY, 0);
- fz_free(ctx, wname);
-#else
- int fd = open(name, O_BINARY | O_RDONLY, 0);
-#endif
- if (fd == -1)
- fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open %s", name);
- return fz_open_fd(ctx, fd);
-}
-
-#ifdef _WIN32
-fz_stream *
-fz_open_file_w(fz_context *ctx, const wchar_t *name)
-{
- int fd = _wopen(name, O_BINARY | O_RDONLY, 0);
- if (fd == -1)
- fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open file %ls", name);
- return fz_open_fd(ctx, fd);
-}
-#endif
-
-/* Memory stream */
-
-static int read_buffer(fz_stream *stm, unsigned char *buf, int len)
-{
- return 0;
-}
-
-static void seek_buffer(fz_stream *stm, int offset, int whence)
-{
- if (whence == 0)
- stm->rp = stm->bp + offset;
- if (whence == 1)
- stm->rp += offset;
- if (whence == 2)
- stm->rp = stm->ep - offset;
- stm->rp = fz_clampp(stm->rp, stm->bp, stm->ep);
- stm->wp = stm->ep;
-}
-
-static void close_buffer(fz_context *ctx, void *state_)
-{
- fz_buffer *state = (fz_buffer *)state_;
- if (state)
- fz_drop_buffer(ctx, state);
-}
-
-fz_stream *
-fz_open_buffer(fz_context *ctx, fz_buffer *buf)
-{
- fz_stream *stm;
-
- fz_keep_buffer(ctx, buf);
- stm = fz_new_stream(ctx, buf, read_buffer, close_buffer);
- stm->seek = seek_buffer;
-
- stm->bp = buf->data;
- stm->rp = buf->data;
- stm->wp = buf->data + buf->len;
- stm->ep = buf->data + buf->len;
-
- stm->pos = buf->len;
-
- return stm;
-}
-
-fz_stream *
-fz_open_memory(fz_context *ctx, unsigned char *data, int len)
-{
- fz_stream *stm;
-
- stm = fz_new_stream(ctx, NULL, read_buffer, close_buffer);
- stm->seek = seek_buffer;
-
- stm->bp = data;
- stm->rp = data;
- stm->wp = data + len;
- stm->ep = data + len;
-
- stm->pos = len;
-
- return stm;
-}
diff --git a/fitz/stm_output.c b/fitz/stm_output.c
deleted file mode 100644
index f98b945e..00000000
--- a/fitz/stm_output.c
+++ /dev/null
@@ -1,100 +0,0 @@
-#include "mupdf/fitz.h"
-
-static int
-file_printf(fz_output *out, const char *fmt, va_list ap)
-{
- FILE *file = (FILE *)out->opaque;
-
- return vfprintf(file, fmt, ap);
-}
-
-static int
-file_write(fz_output *out, const void *buffer, int count)
-{
- FILE *file = (FILE *)out->opaque;
-
- return fwrite(buffer, 1, count, file);
-}
-
-fz_output *
-fz_new_output_with_file(fz_context *ctx, FILE *file)
-{
- fz_output *out = fz_malloc_struct(ctx, fz_output);
- out->ctx = ctx;
- out->opaque = file;
- out->printf = file_printf;
- out->write = file_write;
- out->close = NULL;
- return out;
-}
-
-void
-fz_close_output(fz_output *out)
-{
- if (!out)
- return;
- if (out->close)
- out->close(out);
- fz_free(out->ctx, out);
-}
-
-int
-fz_printf(fz_output *out, const char *fmt, ...)
-{
- int ret;
- va_list ap;
-
- if (!out)
- return 0;
-
- va_start(ap, fmt);
- ret = out->printf(out, fmt, ap);
- va_end(ap);
-
- return ret;
-}
-
-int
-fz_write(fz_output *out, const void *data, int len)
-{
- if (!out)
- return 0;
- return out->write(out, data, len);
-}
-
-int
-fz_puts(fz_output *out, const char *str)
-{
- if (!out)
- return 0;
- return out->write(out, str, strlen(str));
-}
-
-static int
-buffer_printf(fz_output *out, const char *fmt, va_list list)
-{
- fz_buffer *buffer = (fz_buffer *)out->opaque;
-
- return fz_buffer_vprintf(out->ctx, buffer, fmt, list);
-}
-
-static int
-buffer_write(fz_output *out, const void *data, int len)
-{
- fz_buffer *buffer = (fz_buffer *)out->opaque;
-
- fz_write_buffer(out->ctx, buffer, (unsigned char *)data, len);
- return len;
-}
-
-fz_output *
-fz_new_output_with_buffer(fz_context *ctx, fz_buffer *buf)
-{
- fz_output *out = fz_malloc_struct(ctx, fz_output);
- out->ctx = ctx;
- out->opaque = buf;
- out->printf = buffer_printf;
- out->write = buffer_write;
- out->close = NULL;
- return out;
-}
diff --git a/fitz/stm_read.c b/fitz/stm_read.c
deleted file mode 100644
index ee3d1cad..00000000
--- a/fitz/stm_read.c
+++ /dev/null
@@ -1,219 +0,0 @@
-#include "mupdf/fitz.h"
-
-#define MIN_BOMB (100 << 20)
-
-int
-fz_read(fz_stream *stm, unsigned char *buf, int len)
-{
- int count, n;
-
- count = fz_mini(len, stm->wp - stm->rp);
- if (count)
- {
- memcpy(buf, stm->rp, count);
- stm->rp += count;
- }
-
- if (count == len || stm->error || stm->eof)
- return count;
-
- assert(stm->rp == stm->wp);
-
- if (len - count < stm->ep - stm->bp)
- {
- n = stm->read(stm, stm->bp, stm->ep - stm->bp);
- if (n == 0)
- {
- stm->eof = 1;
- }
- else if (n > 0)
- {
- stm->rp = stm->bp;
- stm->wp = stm->bp + n;
- stm->pos += n;
- }
-
- n = fz_mini(len - count, stm->wp - stm->rp);
- if (n)
- {
- memcpy(buf + count, stm->rp, n);
- stm->rp += n;
- count += n;
- }
- }
- else
- {
- n = stm->read(stm, buf + count, len - count);
- if (n == 0)
- {
- stm->eof = 1;
- }
- else if (n > 0)
- {
- stm->pos += n;
- count += n;
- }
- }
-
- return count;
-}
-
-void
-fz_fill_buffer(fz_stream *stm)
-{
- int n;
-
- assert(stm->rp == stm->wp);
-
- if (stm->error || stm->eof)
- return;
-
- fz_try(stm->ctx)
- {
- n = stm->read(stm, stm->bp, stm->ep - stm->bp);
- if (n == 0)
- {
- stm->eof = 1;
- }
- else if (n > 0)
- {
- stm->rp = stm->bp;
- stm->wp = stm->bp + n;
- stm->pos += n;
- }
- }
- fz_catch(stm->ctx)
- {
- /* FIXME: TryLater */
- fz_warn(stm->ctx, "read error; treating as end of file");
- stm->error = 1;
- }
-}
-
-fz_buffer *
-fz_read_all(fz_stream *stm, int initial)
-{
- return fz_read_best(stm, initial, NULL);
-}
-
-fz_buffer *
-fz_read_best(fz_stream *stm, int initial, int *truncated)
-{
- fz_buffer *buf = NULL;
- int n;
- fz_context *ctx = stm->ctx;
-
- fz_var(buf);
-
- if (truncated)
- *truncated = 0;
-
- fz_try(ctx)
- {
- if (initial < 1024)
- initial = 1024;
-
- buf = fz_new_buffer(ctx, initial+1);
-
- while (1)
- {
- if (buf->len == buf->cap)
- fz_grow_buffer(ctx, buf);
-
- if (buf->len >= MIN_BOMB && buf->len / 200 > initial)
- {
- fz_throw(ctx, FZ_ERROR_GENERIC, "compression bomb detected");
- }
-
- n = fz_read(stm, buf->data + buf->len, buf->cap - buf->len);
- if (n == 0)
- break;
-
- buf->len += n;
- }
- }
- fz_catch(ctx)
- {
- /* FIXME: TryLater */
- if (truncated)
- {
- *truncated = 1;
- }
- else
- {
- fz_drop_buffer(ctx, buf);
- fz_rethrow(ctx);
- }
- }
- fz_trim_buffer(ctx, buf);
-
- return buf;
-}
-
-void
-fz_read_line(fz_stream *stm, char *mem, int n)
-{
- char *s = mem;
- int c = EOF;
- while (n > 1)
- {
- c = fz_read_byte(stm);
- if (c == EOF)
- break;
- if (c == '\r') {
- c = fz_peek_byte(stm);
- if (c == '\n')
- fz_read_byte(stm);
- break;
- }
- if (c == '\n')
- break;
- *s++ = c;
- n--;
- }
- if (n)
- *s = '\0';
-}
-
-int
-fz_tell(fz_stream *stm)
-{
- return stm->pos - (stm->wp - stm->rp);
-}
-
-void
-fz_seek(fz_stream *stm, int offset, int whence)
-{
- if (stm->seek)
- {
- if (whence == 1)
- {
- offset = fz_tell(stm) + offset;
- whence = 0;
- }
- if (whence == 0)
- {
- int dist = stm->pos - offset;
- if (dist >= 0 && dist <= stm->wp - stm->bp)
- {
- stm->rp = stm->wp - dist;
- stm->eof = 0;
- return;
- }
- }
- stm->seek(stm, offset, whence);
- stm->eof = 0;
- }
- else if (whence != 2)
- {
- if (whence == 0)
- offset -= fz_tell(stm);
- if (offset < 0)
- fz_warn(stm->ctx, "cannot seek backwards");
- /* dog slow, but rare enough */
- while (offset-- > 0)
- fz_read_byte(stm);
- }
- else
- fz_warn(stm->ctx, "cannot seek");
-}
diff --git a/fitz/text_extract.c b/fitz/text_extract.c
deleted file mode 100644
index e3bf9d19..00000000
--- a/fitz/text_extract.c
+++ /dev/null
@@ -1,1027 +0,0 @@
-#include "mupdf/fitz.h"
-#include "ucdn.h"
-
-/* Extract text into an unsorted span soup. */
-
-#define LINE_DIST 0.9f
-#define SPACE_DIST 0.2f
-#define SPACE_MAX_DIST 0.8f
-#define PARAGRAPH_DIST 0.5f
-
-#undef DEBUG_SPANS
-#undef DEBUG_INTERNALS
-#undef DEBUG_LINE_HEIGHTS
-#undef DEBUG_MASKS
-#undef DEBUG_ALIGN
-#undef DEBUG_INDENTS
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_ADVANCES_H
-
-typedef struct fz_text_device_s fz_text_device;
-
-typedef struct span_soup_s span_soup;
-
-struct fz_text_device_s
-{
- fz_text_sheet *sheet;
- fz_text_page *page;
- span_soup *spans;
- fz_text_span *cur_span;
- int lastchar;
-};
-
-static fz_rect *
-add_point_to_rect(fz_rect *a, const fz_point *p)
-{
- if (p->x < a->x0)
- a->x0 = p->x;
- if (p->x > a->x1)
- a->x1 = p->x;
- if (p->y < a->y0)
- a->y0 = p->y;
- if (p->y > a->y1)
- a->y1 = p->y;
- return a;
-}
-
-fz_rect *
-fz_text_char_bbox(fz_rect *bbox, fz_text_span *span, int i)
-{
- fz_point a, d;
- const fz_point *max;
- fz_text_char *ch;
-
- if (!span || i >= span->len)
- {
- *bbox = fz_empty_rect;
- }
- ch = &span->text[i];
- if (i == span->len-1)
- max = &span->max;
- else
- max = &span->text[i+1].p;
- a.x = 0;
- a.y = span->ascender_max;
- fz_transform_vector(&a, &span->transform);
- d.x = 0;
- d.y = span->descender_min;
- fz_transform_vector(&d, &span->transform);
- bbox->x0 = bbox->x1 = ch->p.x + a.x;
- bbox->y0 = bbox->y1 = ch->p.y + a.y;
- a.x += max->x;
- a.y += max->y;
- add_point_to_rect(bbox, &a);
- a.x = ch->p.x + d.x;
- a.y = ch->p.y + d.y;
- add_point_to_rect(bbox, &a);
- a.x = max->x + d.x;
- a.y = max->y + d.y;
- add_point_to_rect(bbox, &a);
- return bbox;
-}
-
-static void
-add_bbox_to_span(fz_text_span *span)
-{
- fz_point a, d;
- fz_rect *bbox = &span->bbox;
-
- if (!span)
- return;
- a.x = 0;
- a.y = span->ascender_max;
- fz_transform_vector(&a, &span->transform);
- d.x = 0;
- d.y = span->descender_min;
- fz_transform_vector(&d, &span->transform);
- bbox->x0 = bbox->x1 = span->min.x + a.x;
- bbox->y0 = bbox->y1 = span->min.y + a.y;
- a.x += span->max.x;
- a.y += span->max.y;
- add_point_to_rect(bbox, &a);
- a.x = span->min.x + d.x;
- a.y = span->min.y + d.y;
- add_point_to_rect(bbox, &a);
- a.x = span->max.x + d.x;
- a.y = span->max.y + d.y;
- add_point_to_rect(bbox, &a);
-}
-
-struct span_soup_s
-{
- fz_context *ctx;
- int len, cap;
- fz_text_span **spans;
-};
-
-static span_soup *
-new_span_soup(fz_context *ctx)
-{
- span_soup *soup = fz_malloc_struct(ctx, span_soup);
- soup->ctx = ctx;
- soup->len = 0;
- soup->cap = 0;
- soup->spans = NULL;
- return soup;
-}
-
-static void
-free_span_soup(span_soup *soup)
-{
- int i;
-
- if (soup == NULL)
- return;
- for (i = 0; i < soup->len; i++)
- {
- fz_free(soup->ctx, soup->spans[i]);
- }
- fz_free(soup->ctx, soup->spans);
- fz_free(soup->ctx, soup);
-}
-
-static void
-add_span_to_soup(span_soup *soup, fz_text_span *span)
-{
- if (span == NULL)
- return;
- if (soup->len == soup->cap)
- {
- int newcap = (soup->cap ? soup->cap * 2 : 16);
- soup->spans = fz_resize_array(soup->ctx, soup->spans, newcap, sizeof(*soup->spans));
- soup->cap = newcap;
- }
- add_bbox_to_span(span);
- soup->spans[soup->len++] = span;
-}
-
-static fz_text_line *
-push_span(fz_context *ctx, fz_text_device *tdev, fz_text_span *span, int new_line, float distance)
-{
- fz_text_line *line;
- fz_text_block *block;
- fz_text_page *page = tdev->page;
- int prev_not_text = 0;
-
- if (page->len == 0 || page->blocks[page->len-1].type != FZ_PAGE_BLOCK_TEXT)
- prev_not_text = 1;
-
- if (new_line || prev_not_text)
- {
- float size = fz_matrix_expansion(&span->transform);
- /* So, a new line. Part of the same block or not? */
- if (distance == 0 || distance > size * 1.5 || distance < -size * PARAGRAPH_DIST || page->len == 0 || prev_not_text)
- {
- /* New block */
- if (page->len == page->cap)
- {
- int newcap = (page->cap ? page->cap*2 : 4);
- page->blocks = fz_resize_array(ctx, page->blocks, newcap, sizeof(*page->blocks));
- page->cap = newcap;
- }
- block = fz_malloc_struct(ctx, fz_text_block);
- page->blocks[page->len].type = FZ_PAGE_BLOCK_TEXT;
- page->blocks[page->len].u.text = block;
- block->cap = 0;
- block->len = 0;
- block->lines = 0;
- block->bbox = fz_empty_rect;
- page->len++;
- distance = 0;
- }
-
- /* New line */
- block = page->blocks[page->len-1].u.text;
- if (block->len == block->cap)
- {
- int newcap = (block->cap ? block->cap*2 : 4);
- block->lines = fz_resize_array(ctx, block->lines, newcap, sizeof(*block->lines));
- block->cap = newcap;
- }
- block->lines[block->len].first_span = NULL;
- block->lines[block->len].last_span = NULL;
- block->lines[block->len].distance = distance;
- block->lines[block->len].bbox = fz_empty_rect;
- block->len++;
- }
-
- /* Find last line and append to it */
- block = page->blocks[page->len-1].u.text;
- line = &block->lines[block->len-1];
-
- fz_union_rect(&block->lines[block->len-1].bbox, &span->bbox);
- fz_union_rect(&block->bbox, &span->bbox);
- span->base_offset = (new_line ? 0 : distance);
-
- if (!line->first_span)
- {
- line->first_span = line->last_span = span;
- span->next = NULL;
- }
- else
- {
- line->last_span->next = span;
- line->last_span = span;
- }
-
- return line;
-}
-
-#if defined(DEBUG_SPANS) || defined(DEBUG_ALIGN) || defined(DEBUG_INDENTS)
-static void
-dump_span(fz_text_span *s)
-{
- int i;
- for (i=0; i < s->len; i++)
- {
- printf("%c", s->text[i].c);
- }
-}
-#endif
-
-#ifdef DEBUG_ALIGN
-static void
-dump_line(fz_text_line *line)
-{
- int i;
- for (i=0; i < line->len; i++)
- {
- fz_text_span *s = line->spans[i];
- if (s->spacing > 1)
- printf(" ");
- dump_span(s);
- }
- printf("\n");
-}
-#endif
-
-static void
-strain_soup(fz_context *ctx, fz_text_device *tdev)
-{
- span_soup *soup = tdev->spans;
- fz_text_line *last_line = NULL;
- fz_text_span *last_span = NULL;
- int span_num;
-
- /* Really dumb implementation to match what we had before */
- for (span_num=0; span_num < soup->len; span_num++)
- {
- fz_text_span *span = soup->spans[span_num];
- int new_line = 1;
- float distance = 0;
- float spacing = 0;
- soup->spans[span_num] = NULL;
- if (last_span)
- {
- /* If we have a last_span, we must have a last_line */
- /* Do span and last_line share the same baseline? */
- fz_point p, q, perp_r;
- float dot;
- float size = fz_matrix_expansion(&span->transform);
-
-#ifdef DEBUG_SPANS
- {
- printf("Comparing: \"");
- dump_span(last_span);
- printf("\" and \"");
- dump_span(span);
- printf("\"\n");
- }
-#endif
-
- p.x = last_line->first_span->max.x - last_line->first_span->min.x;
- p.y = last_line->first_span->max.y - last_line->first_span->min.y;
- fz_normalize_vector(&p);
- q.x = span->max.x - span->min.x;
- q.y = span->max.y - span->min.y;
- fz_normalize_vector(&q);
-#ifdef DEBUG_SPANS
- printf("last_span=%g %g -> %g %g = %g %g\n", last_span->min.x, last_span->min.y, last_span->max.x, last_span->max.y, p.x, p.y);
- printf("span =%g %g -> %g %g = %g %g\n", span->min.x, span->min.y, span->max.x, span->max.y, q.x, q.y);
-#endif
- perp_r.y = last_line->first_span->min.x - span->min.x;
- perp_r.x = -(last_line->first_span->min.y - span->min.y);
- /* Check if p and q are parallel. If so, then this
- * line is parallel with the last one. */
- dot = p.x * q.x + p.y * q.y;
- if (fabsf(dot) > 0.9995)
- {
- /* If we take the dot product of normalised(p) and
- * perp(r), we get the perpendicular distance from
- * one line to the next (assuming they are parallel). */
- distance = p.x * perp_r.x + p.y * perp_r.y;
- /* We allow 'small' distances of baseline changes
- * to cope with super/subscript. FIXME: We should
- * gather subscript/superscript information here. */
- new_line = (fabsf(distance) > size * LINE_DIST);
- }
- else
- {
- new_line = 1;
- distance = 0;
- }
- if (!new_line)
- {
- fz_point delta;
-
- delta.x = span->min.x - last_span->max.x;
- delta.y = span->min.y - last_span->max.y;
-
- spacing = (p.x * delta.x + p.y * delta.y);
- spacing = fabsf(spacing);
- /* Only allow changes in baseline (subscript/superscript etc)
- * when the spacing is small. */
- if (spacing * fabsf(distance) > size * LINE_DIST && fabsf(distance) > size * 0.1f)
- {
- new_line = 1;
- distance = 0;
- spacing = 0;
- }
- else
- {
- spacing /= size * SPACE_DIST;
- /* Apply the same logic here as when we're adding chars to build spans. */
- if (spacing >= 1 && spacing < (SPACE_MAX_DIST/SPACE_DIST))
- spacing = 1;
- }
- }
-#ifdef DEBUG_SPANS
- printf("dot=%g new_line=%d distance=%g size=%g spacing=%g\n", dot, new_line, distance, size, spacing);
-#endif
- }
- span->spacing = spacing;
- last_line = push_span(ctx, tdev, span, new_line, distance);
- last_span = span;
- }
-}
-
-fz_text_sheet *
-fz_new_text_sheet(fz_context *ctx)
-{
- fz_text_sheet *sheet = fz_malloc(ctx, sizeof *sheet);
- sheet->maxid = 0;
- sheet->style = NULL;
- return sheet;
-}
-
-void
-fz_free_text_sheet(fz_context *ctx, fz_text_sheet *sheet)
-{
- fz_text_style *style;
-
- if (sheet == NULL)
- return;
-
- style = sheet->style;
- while (style)
- {
- fz_text_style *next = style->next;
- fz_drop_font(ctx, style->font);
- fz_free(ctx, style);
- style = next;
- }
- fz_free(ctx, sheet);
-}
-
-static fz_text_style *
-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;
-
- 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_lookup_text_style(fz_context *ctx, fz_text_sheet *sheet, fz_text *text, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha, fz_stroke_state *stroke)
-{
- 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;
- fz_concat(&trm, &tm, ctm);
- size = fz_matrix_expansion(&trm);
- }
- return fz_lookup_text_style_imp(ctx, sheet, size, font, wmode, 0);
-}
-
-fz_text_page *
-fz_new_text_page(fz_context *ctx)
-{
- fz_text_page *page = fz_malloc(ctx, sizeof(*page));
- page->mediabox = fz_empty_rect;
- page->len = 0;
- page->cap = 0;
- page->blocks = NULL;
- page->next = NULL;
- return page;
-}
-
-static void
-fz_free_text_line_contents(fz_context *ctx, fz_text_line *line)
-{
- fz_text_span *span, *next;
- for (span = line->first_span; span; span=next)
- {
- next = span->next;
- fz_free(ctx, span->text);
- fz_free(ctx, span);
- }
-}
-
-static void
-fz_free_text_block(fz_context *ctx, fz_text_block *block)
-{
- fz_text_line *line;
- if (block == NULL)
- return;
- for (line = block->lines; line < block->lines + block->len; line++)
- fz_free_text_line_contents(ctx, line);
- fz_free(ctx, block->lines);
- fz_free(ctx, block);
-}
-
-static void
-fz_free_image_block(fz_context *ctx, fz_image_block *block)
-{
- if (block == NULL)
- return;
- fz_drop_image(ctx, block->image);
- fz_drop_colorspace(ctx, block->cspace);
- fz_free(ctx, block);
-}
-
-void
-fz_free_text_page(fz_context *ctx, fz_text_page *page)
-{
- fz_page_block *block;
- if (page == NULL)
- return;
- for (block = page->blocks; block < page->blocks + page->len; block++)
- {
- switch (block->type)
- {
- case FZ_PAGE_BLOCK_TEXT:
- fz_free_text_block(ctx, block->u.text);
- break;
- case FZ_PAGE_BLOCK_IMAGE:
- fz_free_image_block(ctx, block->u.image);
- break;
- }
- }
- fz_free(ctx, page->blocks);
- fz_free(ctx, page);
-}
-
-static fz_text_span *
-fz_new_text_span(fz_context *ctx, const fz_point *p, int wmode, const fz_matrix *trm)
-{
- fz_text_span *span = fz_malloc_struct(ctx, fz_text_span);
- span->ascender_max = 0;
- span->descender_min = 0;
- span->cap = 0;
- span->len = 0;
- span->min = *p;
- span->max = *p;
- span->wmode = wmode;
- span->transform.a = trm->a;
- span->transform.b = trm->b;
- span->transform.c = trm->c;
- span->transform.d = trm->d;
- span->transform.e = 0;
- span->transform.f = 0;
- span->text = NULL;
- span->next = NULL;
- return span;
-}
-
-static void
-add_char_to_span(fz_context *ctx, fz_text_span *span, int c, fz_point *p, fz_point *max, fz_text_style *style)
-{
- if (span->len == span->cap)
- {
- int newcap = (span->cap ? span->cap * 2 : 16);
- span->text = fz_resize_array(ctx, span->text, newcap, sizeof(fz_text_char));
- span->cap = newcap;
- span->bbox = fz_empty_rect;
- }
- span->max = *max;
- if (style->ascender > span->ascender_max)
- span->ascender_max = style->ascender;
- if (style->descender < span->descender_min)
- span->descender_min = style->descender;
- span->text[span->len].c = c;
- span->text[span->len].p = *p;
- span->text[span->len].style = style;
- span->len++;
-}
-
-static void
-fz_add_text_char_imp(fz_context *ctx, fz_text_device *dev, fz_text_style *style, int c, fz_matrix *trm, float adv, int wmode)
-{
- int can_append = 1;
- int add_space = 0;
- fz_point dir, ndir, p, q;
- float size;
- fz_point delta;
- float spacing = 0;
- float base_offset = 0;
-
- if (wmode == 0)
- {
- dir.x = 1;
- dir.y = 0;
- }
- else
- {
- dir.x = 0;
- dir.y = 1;
- }
- fz_transform_vector(&dir, trm);
- ndir = dir;
- fz_normalize_vector(&ndir);
- /* dir = direction vector for motion. ndir = normalised(dir) */
-
- size = fz_matrix_expansion(trm);
-
- if (dev->cur_span == NULL ||
- trm->a != dev->cur_span->transform.a || trm->b != dev->cur_span->transform.b ||
- trm->c != dev->cur_span->transform.c || trm->d != dev->cur_span->transform.d)
- {
- /* If the matrix has changed (or if we don't have a span at
- * all), then we can't append. */
-#ifdef DEBUG_SPANS
- printf("Transform changed\n");
-#endif
- can_append = 0;
- }
- else
- {
- /* Calculate how far we've moved since the end of the current
- * span. */
- delta.x = trm->e - dev->cur_span->max.x;
- delta.y = trm->f - dev->cur_span->max.y;
-
- /* The transform has not changed, so we know we're in the same
- * direction. Calculate 2 distances; how far off the previous
- * baseline we are, together with how far along the baseline
- * we are from the expected position. */
- spacing = ndir.x * delta.x + ndir.y * delta.y;
- base_offset = -ndir.y * delta.x + ndir.x * delta.y;
-
- spacing /= size * SPACE_DIST;
- spacing = fabsf(spacing);
- if (fabsf(base_offset) < size * 0.1)
- {
- /* Only a small amount off the baseline - we'll take this */
- if (spacing < 1.0)
- {
- /* Motion is in line, and small. */
- }
- else if (spacing >= 1 && spacing < (SPACE_MAX_DIST/SPACE_DIST))
- {
- /* Motion is in line, but large enough
- * to warrant us adding a space */
- if (dev->lastchar != ' ' && wmode == 0)
- add_space = 1;
- }
- else
- {
- /* Motion is in line, but too large - split to a new span */
- can_append = 0;
- }
- }
- else
- {
- can_append = 0;
- spacing = 0;
- }
- }
-
-#ifdef DEBUG_SPANS
- printf("%c%c append=%d space=%d size=%g spacing=%g base_offset=%g\n", dev->lastchar, c, can_append, add_space, size, spacing, base_offset);
-#endif
-
- p.x = trm->e;
- p.y = trm->f;
- if (can_append == 0)
- {
- /* Start a new span */
- add_span_to_soup(dev->spans, dev->cur_span);
- dev->cur_span = NULL;
- dev->cur_span = fz_new_text_span(ctx, &p, wmode, trm);
- dev->cur_span->spacing = 0;
- }
- if (add_space)
- {
- q.x = - 0.2f;
- q.y = 0;
- fz_transform_point(&q, trm);
- add_char_to_span(ctx, dev->cur_span, ' ', &p, &q, style);
- }
- /* Advance the matrix */
- q.x = trm->e += adv * dir.x;
- q.y = trm->f += adv * dir.y;
- add_char_to_span(ctx, dev->cur_span, c, &p, &q, style);
-}
-
-static void
-fz_add_text_char(fz_context *ctx, fz_text_device *dev, fz_text_style *style, int c, fz_matrix *trm, float adv, int wmode)
-{
- switch (c)
- {
- case -1: /* ignore when one unicode character maps to multiple glyphs */
- break;
- case 0xFB00: /* ff */
- fz_add_text_char_imp(ctx, dev, style, 'f', trm, adv/2, wmode);
- fz_add_text_char_imp(ctx, dev, style, 'f', trm, adv/2, wmode);
- break;
- case 0xFB01: /* fi */
- fz_add_text_char_imp(ctx, dev, style, 'f', trm, adv/2, wmode);
- fz_add_text_char_imp(ctx, dev, style, 'i', trm, adv/2, wmode);
- break;
- case 0xFB02: /* fl */
- fz_add_text_char_imp(ctx, dev, style, 'f', trm, adv/2, wmode);
- fz_add_text_char_imp(ctx, dev, style, 'l', trm, adv/2, wmode);
- break;
- case 0xFB03: /* ffi */
- fz_add_text_char_imp(ctx, dev, style, 'f', trm, adv/3, wmode);
- fz_add_text_char_imp(ctx, dev, style, 'f', trm, adv/3, wmode);
- fz_add_text_char_imp(ctx, dev, style, 'i', trm, adv/3, wmode);
- break;
- case 0xFB04: /* ffl */
- fz_add_text_char_imp(ctx, dev, style, 'f', trm, adv/3, wmode);
- fz_add_text_char_imp(ctx, dev, style, 'f', trm, adv/3, wmode);
- fz_add_text_char_imp(ctx, dev, style, 'l', trm, adv/3, wmode);
- break;
- case 0xFB05: /* long st */
- case 0xFB06: /* st */
- fz_add_text_char_imp(ctx, dev, style, 's', trm, adv/2, wmode);
- fz_add_text_char_imp(ctx, dev, style, 't', trm, adv/2, wmode);
- break;
- default:
- fz_add_text_char_imp(ctx, dev, style, c, trm, adv, wmode);
- break;
- }
-}
-
-static void
-fz_text_extract(fz_context *ctx, fz_text_device *dev, fz_text *text, const fz_matrix *ctm, fz_text_style *style)
-{
- fz_font *font = text->font;
- FT_Face face = font->ft_face;
- fz_matrix tm = text->trm;
- fz_matrix trm;
- float adv;
- float ascender = 1;
- float descender = 0;
- int multi;
- int i, j, err;
-
- if (text->len == 0)
- return;
-
- 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);
- }
- else if (font->t3procs && !fz_is_empty_rect(&font->bbox))
- {
- ascender = font->bbox.y1;
- descender = font->bbox.y0;
- }
- style->ascender = ascender;
- style->descender = descender;
-
- tm.e = 0;
- tm.f = 0;
- fz_concat(&trm, &tm, ctm);
-
- for (i = 0; i < text->len; i++)
- {
- /* Calculate new pen location and delta */
- tm.e = text->items[i].x;
- tm.f = text->items[i].y;
- fz_concat(&trm, &tm, ctm);
-
- /* Calculate bounding box and new pen position based on font metrics */
- if (font->ft_face)
- {
- FT_Fixed ftadv = 0;
- int mask = FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING | FT_LOAD_IGNORE_TRANSFORM;
-
- /* 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);
- }
- else
- {
- adv = font->t3widths[text->items[i].gid];
- }
-
- /* 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, &trm, adv, text->wmode);
- }
- else
- {
- for (j = 0; j < multi; j++)
- {
- fz_add_text_char(ctx, dev, style, text->items[i + j].ucs, &trm, adv/multi, text->wmode);
- }
- i += j - 1;
- }
-
- dev->lastchar = text->items[i].ucs;
- }
-}
-
-static void
-fz_text_fill_text(fz_device *dev, fz_text *text, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- fz_text_device *tdev = dev->user;
- fz_text_style *style;
- style = fz_lookup_text_style(dev->ctx, tdev->sheet, text, ctm, colorspace, color, alpha, NULL);
- fz_text_extract(dev->ctx, tdev, text, ctm, style);
-}
-
-static void
-fz_text_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, const fz_matrix *ctm,
- fz_colorspace *colorspace, float *color, float alpha)
-{
- fz_text_device *tdev = dev->user;
- fz_text_style *style;
- style = fz_lookup_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, const fz_matrix *ctm, int accumulate)
-{
- fz_text_device *tdev = dev->user;
- fz_text_style *style;
- style = fz_lookup_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, const fz_matrix *ctm)
-{
- fz_text_device *tdev = dev->user;
- fz_text_style *style;
- style = fz_lookup_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, const fz_matrix *ctm)
-{
- fz_text_device *tdev = dev->user;
- fz_text_style *style;
- style = fz_lookup_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_fill_image_mask(fz_device *dev, fz_image *img, const fz_matrix *ctm,
- fz_colorspace *cspace, float *color, float alpha)
-{
- fz_text_device *tdev = dev->user;
- fz_text_page *page = tdev->page;
- fz_image_block *block;
- fz_context *ctx = dev->ctx;
-
- /* If the alpha is less than 50% then it's probably a watermark or
- * effect or something. Skip it */
- if (alpha < 0.5)
- return;
-
- /* New block */
- if (page->len == page->cap)
- {
- int newcap = (page->cap ? page->cap*2 : 4);
- page->blocks = fz_resize_array(ctx, page->blocks, newcap, sizeof(*page->blocks));
- page->cap = newcap;
- }
- block = fz_malloc_struct(ctx, fz_image_block);
- page->blocks[page->len].type = FZ_PAGE_BLOCK_IMAGE;
- page->blocks[page->len].u.image = block;
- block->image = fz_keep_image(ctx, img);
- block->cspace = fz_keep_colorspace(ctx, cspace);
- if (cspace)
- memcpy(block->colors, color, sizeof(block->colors[0])*cspace->n);
- page->len++;
-}
-
-static void
-fz_text_fill_image(fz_device *dev, fz_image *img, const fz_matrix *ctm, float alpha)
-{
- fz_text_fill_image_mask(dev, img, ctm, NULL, NULL, alpha);
-}
-
-static int
-fz_bidi_direction(int bidiclass, int curdir)
-{
- switch (bidiclass)
- {
- /* strong */
- case UCDN_BIDI_CLASS_L: return 1;
- case UCDN_BIDI_CLASS_R: return -1;
- case UCDN_BIDI_CLASS_AL: return -1;
-
- /* weak */
- case UCDN_BIDI_CLASS_EN:
- case UCDN_BIDI_CLASS_ES:
- case UCDN_BIDI_CLASS_ET:
- case UCDN_BIDI_CLASS_AN:
- case UCDN_BIDI_CLASS_CS:
- case UCDN_BIDI_CLASS_NSM:
- case UCDN_BIDI_CLASS_BN:
- return curdir;
-
- /* neutral */
- case UCDN_BIDI_CLASS_B:
- case UCDN_BIDI_CLASS_S:
- case UCDN_BIDI_CLASS_WS:
- case UCDN_BIDI_CLASS_ON:
- return curdir;
-
- /* embedding, override, pop ... we don't support them */
- default:
- return 0;
- }
-}
-
-static void
-fz_bidi_reorder_run(fz_text_span *span, int a, int b, int dir)
-{
- if (a < b && dir == -1)
- {
- fz_text_char c;
- int m = a + (b - a) / 2;
- while (a < m)
- {
- b--;
- c = span->text[a];
- span->text[a] = span->text[b];
- span->text[b] = c;
- a++;
- }
- }
-}
-
-static void
-fz_bidi_reorder_span(fz_text_span *span)
-{
- int a, b, dir, curdir;
-
- a = 0;
- curdir = 1;
- for (b = 0; b < span->len; b++)
- {
- dir = fz_bidi_direction(ucdn_get_bidi_class(span->text[b].c), curdir);
- if (dir != curdir)
- {
- fz_bidi_reorder_run(span, a, b, curdir);
- curdir = dir;
- a = b;
- }
- }
- fz_bidi_reorder_run(span, a, b, curdir);
-}
-
-static void
-fz_bidi_reorder_text_page(fz_context *ctx, fz_text_page *page)
-{
- fz_page_block *pageblock;
- fz_text_block *block;
- fz_text_line *line;
- fz_text_span *span;
-
- for (pageblock = page->blocks; pageblock < page->blocks + page->len; pageblock++)
- if (pageblock->type == FZ_PAGE_BLOCK_TEXT)
- for (block = pageblock->u.text, line = block->lines; line < block->lines + block->len; line++)
- for (span = line->first_span; span; span = span->next)
- fz_bidi_reorder_span(span);
-}
-
-static void
-fz_text_begin_page(fz_device *dev, const fz_rect *mediabox, const fz_matrix *ctm)
-{
- fz_context *ctx = dev->ctx;
- fz_text_device *tdev = dev->user;
-
- if (tdev->page->len)
- {
- tdev->page->next = fz_new_text_page(ctx);
- tdev->page = tdev->page->next;
- }
-
- tdev->page->mediabox = *mediabox;
- fz_transform_rect(&tdev->page->mediabox, ctm);
-
- tdev->spans = new_span_soup(ctx);
-}
-
-static void
-fz_text_end_page(fz_device *dev)
-{
- fz_context *ctx = dev->ctx;
- fz_text_device *tdev = dev->user;
-
- add_span_to_soup(tdev->spans, tdev->cur_span);
- tdev->cur_span = NULL;
-
- strain_soup(ctx, tdev);
- free_span_soup(tdev->spans);
- tdev->spans = NULL;
-
- /* TODO: smart sorting of blocks in reading order */
- /* TODO: unicode NFC normalization */
-
- fz_bidi_reorder_text_page(ctx, tdev->page);
-}
-
-static void
-fz_text_free_user(fz_device *dev)
-{
- fz_text_device *tdev = dev->user;
- free_span_soup(tdev->spans);
- fz_free(dev->ctx, tdev);
-}
-
-fz_device *
-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->sheet = sheet;
- tdev->page = page;
- tdev->spans = NULL;
- tdev->cur_span = NULL;
- tdev->lastchar = ' ';
-
- dev = fz_new_device(ctx, tdev);
- dev->hints = FZ_IGNORE_IMAGE | FZ_IGNORE_SHADE;
- dev->begin_page = fz_text_begin_page;
- dev->end_page = fz_text_end_page;
- dev->free_user = fz_text_free_user;
- dev->fill_text = fz_text_fill_text;
- dev->stroke_text = fz_text_stroke_text;
- dev->clip_text = fz_text_clip_text;
- dev->clip_stroke_text = fz_text_clip_stroke_text;
- dev->ignore_text = fz_text_ignore_text;
- dev->fill_image = fz_text_fill_image;
- dev->fill_image_mask = fz_text_fill_image_mask;
-
- return dev;
-}
diff --git a/fitz/text_output.c b/fitz/text_output.c
deleted file mode 100644
index d3241131..00000000
--- a/fitz/text_output.c
+++ /dev/null
@@ -1,400 +0,0 @@
-#include "mupdf/fitz.h"
-
-#define SUBSCRIPT_OFFSET 0.2f
-#define SUPERSCRIPT_OFFSET -0.2f
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
-/* 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(fz_output *out, fz_text_style *style)
-{
- int script = style->script;
- fz_printf(out, "<span class=\"s%d\">", style->id);
- while (script-- > 0)
- fz_printf(out, "<sup>");
- while (++script < 0)
- fz_printf(out, "<sub>");
-}
-
-static void
-fz_print_style_end(fz_output *out, fz_text_style *style)
-{
- int script = style->script;
- while (script-- > 0)
- fz_printf(out, "</sup>");
- while (++script < 0)
- fz_printf(out, "</sub>");
- fz_printf(out, "</span>");
-}
-
-static void
-fz_print_style(fz_output *out, fz_text_style *style)
-{
- char *s = strchr(style->font->name, '+');
- s = s ? s + 1 : style->font->name;
- fz_printf(out, "span.s%d{font-family:\"%s\";font-size:%gpt;",
- style->id, s, style->size);
- if (font_is_italic(style->font))
- fz_printf(out, "font-style:italic;");
- if (font_is_bold(style->font))
- fz_printf(out, "font-weight:bold;");
- fz_printf(out, "}\n");
-}
-
-void
-fz_print_text_sheet(fz_context *ctx, fz_output *out, fz_text_sheet *sheet)
-{
- fz_text_style *style;
- for (style = sheet->style; style; style = style->next)
- fz_print_style(out, style);
-}
-
-static void
-send_data_base64(fz_output *out, fz_buffer *buffer)
-{
- int i, len;
- static const char set[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
- len = buffer->len/3;
- for (i = 0; i < len; i++)
- {
- int c = buffer->data[3*i];
- int d = buffer->data[3*i+1];
- int e = buffer->data[3*i+2];
- if ((i & 15) == 0)
- fz_printf(out, "\n");
- fz_printf(out, "%c%c%c%c", set[c>>2], set[((c&3)<<4)|(d>>4)], set[((d&15)<<2)|(e>>6)], set[e & 63]);
- }
- i *= 3;
- switch (buffer->len-i)
- {
- case 2:
- {
- int c = buffer->data[i];
- int d = buffer->data[i+1];
- fz_printf(out, "%c%c%c=", set[c>>2], set[((c&3)<<4)|(d>>4)], set[((d&15)<<2)]);
- break;
- }
- case 1:
- {
- int c = buffer->data[i];
- fz_printf(out, "%c%c==", set[c>>2], set[(c&3)<<4]);
- break;
- }
- default:
- case 0:
- break;
- }
-}
-
-void
-fz_print_text_page_html(fz_context *ctx, fz_output *out, fz_text_page *page)
-{
- int block_n, line_n, ch_n;
- fz_text_style *style = NULL;
- fz_text_line *line;
- fz_text_span *span;
- void *last_region = NULL;
-
- fz_printf(out, "<div class=\"page\">\n");
-
- for (block_n = 0; block_n < page->len; block_n++)
- {
- switch (page->blocks[block_n].type)
- {
- case FZ_PAGE_BLOCK_TEXT:
- {
- fz_text_block * block = page->blocks[block_n].u.text;
- fz_printf(out, "<div class=\"block\"><p>\n");
- for (line_n = 0; line_n < block->len; line_n++)
- {
- int lastcol=-1;
- line = &block->lines[line_n];
- style = NULL;
-
- if (line->region != last_region)
- {
- if (last_region)
- fz_printf(out, "</div>");
- fz_printf(out, "<div class=\"metaline\">");
- last_region = line->region;
- }
- fz_printf(out, "<div class=\"line\"");
-#ifdef DEBUG_INTERNALS
- if (line->region)
- fz_printf(out, " region=\"%x\"", line->region);
-#endif
- fz_printf(out, ">");
- for (span = line->first_span; span; span = span->next)
- {
- float size = fz_matrix_expansion(&span->transform);
- float base_offset = span->base_offset / size;
-
- if (lastcol != span->column)
- {
- if (lastcol >= 0)
- {
- fz_printf(out, "</div>");
- }
- /* If we skipped any columns then output some spacer spans */
- while (lastcol < span->column-1)
- {
- fz_printf(out, "<div class=\"cell\"></div>");
- lastcol++;
- }
- lastcol++;
- /* Now output the span to contain this entire column */
- fz_printf(out, "<div class=\"cell\" style=\"");
- {
- fz_text_span *sn;
- for (sn = span->next; sn; sn = sn->next)
- {
- if (sn->column != lastcol)
- break;
- }
- fz_printf(out, "width:%g%%;align:%s", span->column_width, (span->align == 0 ? "left" : (span->align == 1 ? "center" : "right")));
- }
- if (span->indent > 1)
- fz_printf(out, ";padding-left:1em;text-indent:-1em");
- if (span->indent < -1)
- fz_printf(out, ";text-indent:1em");
- fz_printf(out, "\">");
- }
-#ifdef DEBUG_INTERNALS
- fz_printf(out, "<span class=\"internal_span\"");
- if (span->column)
- fz_printf(out, " col=\"%x\"", span->column);
- fz_printf(out, ">");
-#endif
- if (span->spacing >= 1)
- fz_printf(out, " ");
- if (base_offset > SUBSCRIPT_OFFSET)
- fz_printf(out, "<sub>");
- else if (base_offset < SUPERSCRIPT_OFFSET)
- fz_printf(out, "<sup>");
- for (ch_n = 0; ch_n < span->len; ch_n++)
- {
- fz_text_char *ch = &span->text[ch_n];
- if (style != ch->style)
- {
- if (style)
- fz_print_style_end(out, style);
- fz_print_style_begin(out, ch->style);
- style = ch->style;
- }
-
- if (ch->c == '<')
- fz_printf(out, "&lt;");
- else if (ch->c == '>')
- fz_printf(out, "&gt;");
- else if (ch->c == '&')
- fz_printf(out, "&amp;");
- else if (ch->c >= 32 && ch->c <= 127)
- fz_printf(out, "%c", ch->c);
- else
- fz_printf(out, "&#x%x;", ch->c);
- }
- if (style)
- {
- fz_print_style_end(out, style);
- style = NULL;
- }
- if (base_offset > SUBSCRIPT_OFFSET)
- fz_printf(out, "</sub>");
- else if (base_offset < SUPERSCRIPT_OFFSET)
- fz_printf(out, "</sup>");
-#ifdef DEBUG_INTERNALS
- fz_printf(out, "</span>");
-#endif
- }
- /* Close our floating span */
- fz_printf(out, "</div>");
- /* Close the line */
- fz_printf(out, "</div>");
- fz_printf(out, "\n");
- }
- /* Close the metaline */
- fz_printf(out, "</div>");
- last_region = NULL;
- fz_printf(out, "</p></div>\n");
- break;
- }
- case FZ_PAGE_BLOCK_IMAGE:
- {
- fz_image_block *image = page->blocks[block_n].u.image;
- fz_printf(out, "<img width=%d height=%d src=\"data:", image->image->w, image->image->h);
- switch (image->image->buffer == NULL ? FZ_IMAGE_JPX : image->image->buffer->params.type)
- {
- case FZ_IMAGE_JPEG:
- fz_printf(out, "image/jpeg;base64,");
- send_data_base64(out, image->image->buffer->buffer);
- break;
- case FZ_IMAGE_PNG:
- fz_printf(out, "image/png;base64,");
- send_data_base64(out, image->image->buffer->buffer);
- break;
- default:
- {
- fz_buffer *buf = fz_image_as_png(ctx, image->image, image->image->w, image->image->h);
- fz_printf(out, "image/png;base64,");
- send_data_base64(out, buf);
- fz_drop_buffer(ctx, buf);
- break;
- }
- }
- fz_printf(out, "\">\n");
- break;
- }
- }
- }
-
- fz_printf(out, "</div>\n");
-}
-
-void
-fz_print_text_page_xml(fz_context *ctx, fz_output *out, fz_text_page *page)
-{
- int block_n;
-
- fz_printf(out, "<page width=\"%g\" height=\"%g\">\n",
- page->mediabox.x1 - page->mediabox.x0,
- page->mediabox.y1 - page->mediabox.y0);
-
- for (block_n = 0; block_n < page->len; block_n++)
- {
- switch (page->blocks[block_n].type)
- {
- case FZ_PAGE_BLOCK_TEXT:
- {
- fz_text_block *block = page->blocks[block_n].u.text;
- fz_text_line *line;
- char *s;
-
- fz_printf(out, "<block bbox=\"%g %g %g %g\">\n",
- block->bbox.x0, block->bbox.y0, block->bbox.x1, block->bbox.y1);
- for (line = block->lines; line < block->lines + block->len; line++)
- {
- fz_text_span *span;
- fz_printf(out, "<line bbox=\"%g %g %g %g\">\n",
- line->bbox.x0, line->bbox.y0, line->bbox.x1, line->bbox.y1);
- for (span = line->first_span; span; span = span->next)
- {
- fz_text_style *style = NULL;
- int char_num;
- for (char_num = 0; char_num < span->len; char_num++)
- {
- fz_text_char *ch = &span->text[char_num];
- if (ch->style != style)
- {
- if (style)
- {
- fz_printf(out, "</span>\n");
- }
- style = ch->style;
- s = strchr(style->font->name, '+');
- s = s ? s + 1 : style->font->name;
- fz_printf(out, "<span bbox=\"%g %g %g %g\" font=\"%s\" size=\"%g\">\n",
- span->bbox.x0, span->bbox.y0, span->bbox.x1, span->bbox.y1,
- s, style->size);
- }
- {
- fz_rect rect;
- fz_text_char_bbox(&rect, span, char_num);
- fz_printf(out, "<char bbox=\"%g %g %g %g\" x=\"%g\" y=\"%g\" c=\"",
- rect.x0, rect.y0, rect.x1, rect.y1, ch->p.x, ch->p.y);
- }
- switch (ch->c)
- {
- case '<': fz_printf(out, "&lt;"); break;
- case '>': fz_printf(out, "&gt;"); break;
- case '&': fz_printf(out, "&amp;"); break;
- case '"': fz_printf(out, "&quot;"); break;
- case '\'': fz_printf(out, "&apos;"); break;
- default:
- if (ch->c >= 32 && ch->c <= 127)
- fz_printf(out, "%c", ch->c);
- else
- fz_printf(out, "&#x%x;", ch->c);
- break;
- }
- fz_printf(out, "\"/>\n");
- }
- if (style)
- fz_printf(out, "</span>\n");
- }
- fz_printf(out, "</line>\n");
- }
- fz_printf(out, "</block>\n");
- break;
- }
- case FZ_PAGE_BLOCK_IMAGE:
- {
- break;
- }
- }
- }
- fz_printf(out, "</page>\n");
-}
-
-void
-fz_print_text_page(fz_context *ctx, fz_output *out, fz_text_page *page)
-{
- int block_n;
-
- for (block_n = 0; block_n < page->len; block_n++)
- {
- switch (page->blocks[block_n].type)
- {
- case FZ_PAGE_BLOCK_TEXT:
- {
- fz_text_block *block = page->blocks[block_n].u.text;
- fz_text_line *line;
- fz_text_char *ch;
- char utf[10];
- int i, n;
-
- for (line = block->lines; line < block->lines + block->len; line++)
- {
- fz_text_span *span;
- for (span = line->first_span; span; span = span->next)
- {
- for (ch = span->text; ch < span->text + span->len; ch++)
- {
- n = fz_runetochar(utf, ch->c);
- for (i = 0; i < n; i++)
- fz_printf(out, "%c", utf[i]);
- }
- }
- fz_printf(out, "\n");
- }
- fz_printf(out, "\n");
- break;
- }
- case FZ_PAGE_BLOCK_IMAGE:
- break;
- }
- }
-}
diff --git a/fitz/text_paragraph.c b/fitz/text_paragraph.c
deleted file mode 100644
index 51062938..00000000
--- a/fitz/text_paragraph.c
+++ /dev/null
@@ -1,1500 +0,0 @@
-#include "mupdf/fitz.h"
-
-/* Assemble span soup into blocks and lines. */
-
-#define MY_EPSILON 0.001f
-
-#undef DEBUG_LINE_HEIGHTS
-#undef DEBUG_MASKS
-#undef DEBUG_ALIGN
-#undef DEBUG_INDENTS
-
-#undef SPOT_LINE_NUMBERS
-
-typedef struct line_height_s
-{
- float height;
- int count;
- fz_text_style *style;
-} line_height;
-
-typedef struct line_heights_s
-{
- fz_context *ctx;
- int cap;
- int len;
- line_height *lh;
-} line_heights;
-
-static line_heights *
-new_line_heights(fz_context *ctx)
-{
- line_heights *lh = fz_malloc_struct(ctx, line_heights);
- lh->ctx = ctx;
- return lh;
-}
-
-static void
-free_line_heights(line_heights *lh)
-{
- if (!lh)
- return;
- fz_free(lh->ctx, lh->lh);
- fz_free(lh->ctx, lh);
-}
-
-static void
-insert_line_height(line_heights *lh, fz_text_style *style, float height)
-{
- int i;
-
-#ifdef DEBUG_LINE_HEIGHTS
- printf("style=%x height=%g\n", style, height);
-#endif
-
- /* If we have one already, add it in */
- for (i=0; i < lh->len; i++)
- {
- /* Match if we are within 5% */
- if (lh->lh[i].style == style && lh->lh[i].height * 0.95 <= height && lh->lh[i].height * 1.05 >= height)
- {
- /* Ensure that the average height is correct */
- lh->lh[i].height = (lh->lh[i].height * lh->lh[i].count + height) / (lh->lh[i].count+1);
- lh->lh[i].count++;
- return;
- }
- }
-
- /* Otherwise extend (if required) and add it */
- if (lh->cap == lh->len)
- {
- int newcap = (lh->cap ? lh->cap * 2 : 4);
- lh->lh = fz_resize_array(lh->ctx, lh->lh, newcap, sizeof(line_height));
- lh->cap = newcap;
- }
-
- lh->lh[lh->len].count = 1;
- lh->lh[lh->len].height = height;
- lh->lh[lh->len].style = style;
- lh->len++;
-}
-
-static void
-cull_line_heights(line_heights *lh)
-{
- int i, j, k;
-
-#ifdef DEBUG_LINE_HEIGHTS
- printf("Before culling:\n");
- for (i = 0; i < lh->len; i++)
- {
- fz_text_style *style = lh->lh[i].style;
- printf("style=%x height=%g count=%d\n", style, lh->lh[i].height, lh->lh[i].count);
- }
-#endif
- for (i = 0; i < lh->len; i++)
- {
- fz_text_style *style = lh->lh[i].style;
- int count = lh->lh[i].count;
- int max = i;
-
- /* Find the max for this style */
- for (j = i+1; j < lh->len; j++)
- {
- if (lh->lh[j].style == style && lh->lh[j].count > count)
- {
- max = j;
- count = lh->lh[j].count;
- }
- }
-
- /* Destroy all the ones other than the max */
- if (max != i)
- {
- lh->lh[i].count = count;
- lh->lh[i].height = lh->lh[max].height;
- lh->lh[max].count = 0;
- }
- j = i+1;
- for (k = j; k < lh->len; k++)
- {
- if (lh->lh[k].style != style)
- lh->lh[j++] = lh->lh[k];
- }
- lh->len = j;
- }
-#ifdef DEBUG_LINE_HEIGHTS
- printf("After culling:\n");
- for (i = 0; i < lh->len; i++)
- {
- fz_text_style *style = lh->lh[i].style;
- printf("style=%x height=%g count=%d\n", style, lh->lh[i].height, lh->lh[i].count);
- }
-#endif
-}
-
-static float
-line_height_for_style(line_heights *lh, fz_text_style *style)
-{
- int i;
-
- for (i=0; i < lh->len; i++)
- {
- if (lh->lh[i].style == style)
- return lh->lh[i].height;
- }
- return 0.0; /* Never reached */
-}
-
-static void
-split_block(fz_context *ctx, fz_text_page *page, int block_num, int linenum)
-{
- int split_len;
- fz_text_block *block, *block2;
-
- if (page->len == page->cap)
- {
- int new_cap = fz_maxi(16, page->cap * 2);
- page->blocks = fz_resize_array(ctx, page->blocks, new_cap, sizeof(*page->blocks));
- page->cap = new_cap;
- }
-
- memmove(page->blocks+block_num+1, page->blocks+block_num, (page->len - block_num)*sizeof(*page->blocks));
- page->len++;
-
- block2 = fz_malloc_struct(ctx, fz_text_block);
- block = page->blocks[block_num].u.text;
-
- page->blocks[block_num+1].type = FZ_PAGE_BLOCK_TEXT;
- page->blocks[block_num+1].u.text = block2;
- split_len = block->len - linenum;
- block2->bbox = block->bbox; /* FIXME! */
- block2->cap = 0;
- block2->len = 0;
- block2->lines = NULL;
- block2->lines = fz_malloc_array(ctx, split_len, sizeof(fz_text_line));
- block2->cap = block2->len;
- block2->len = split_len;
- block->len = linenum;
- memcpy(block2->lines, block->lines + linenum, split_len * sizeof(fz_text_line));
- block2->lines[0].distance = 0;
-}
-
-static inline int
-is_unicode_wspace(int c)
-{
- return (c == 9 || /* TAB */
- c == 0x0a || /* HT */
- c == 0x0b || /* LF */
- c == 0x0c || /* VT */
- c == 0x0d || /* FF */
- c == 0x20 || /* CR */
- c == 0x85 || /* NEL */
- c == 0xA0 || /* No break space */
- c == 0x1680 || /* Ogham space mark */
- c == 0x180E || /* Mongolian Vowel Separator */
- c == 0x2000 || /* En quad */
- c == 0x2001 || /* Em quad */
- c == 0x2002 || /* En space */
- c == 0x2003 || /* Em space */
- c == 0x2004 || /* Three-per-Em space */
- c == 0x2005 || /* Four-per-Em space */
- c == 0x2006 || /* Five-per-Em space */
- c == 0x2007 || /* Figure space */
- c == 0x2008 || /* Punctuation space */
- c == 0x2009 || /* Thin space */
- c == 0x200A || /* Hair space */
- c == 0x2028 || /* Line separator */
- c == 0x2029 || /* Paragraph separator */
- c == 0x202F || /* Narrow no-break space */
- c == 0x205F || /* Medium mathematical space */
- c == 0x3000); /* Ideographic space */
-}
-
-static inline int
-is_unicode_bullet(int c)
-{
- /* The last 2 aren't strictly bullets, but will do for our usage here */
- return (c == 0x2022 || /* Bullet */
- c == 0x2023 || /* Triangular bullet */
- c == 0x25e6 || /* White bullet */
- c == 0x2043 || /* Hyphen bullet */
- c == 0x2219 || /* Bullet operator */
- c == 149 || /* Ascii bullet */
- c == '*');
-}
-
-static inline int
-is_number(int c)
-{
- return ((c >= '0' && c <= '9') ||
- (c == '.'));
-}
-
-static inline int
-is_latin_char(int c)
-{
- return ((c >= 'A' && c <= 'Z') ||
- (c >= 'a' && c <= 'z'));
-}
-
-static inline int
-is_roman(int c)
-{
- return (c == 'i' || c == 'I' ||
- c == 'v' || c == 'V' ||
- c == 'x' || c == 'X' ||
- c == 'l' || c == 'L' ||
- c == 'c' || c == 'C' ||
- c == 'm' || c == 'M');
-}
-
-static int
-is_list_entry(fz_text_line *line, fz_text_span *span, int *char_num_ptr)
-{
- int char_num;
- fz_text_char *chr;
-
- /* First, skip over any whitespace */
- for (char_num = 0; char_num < span->len; char_num++)
- {
- chr = &span->text[char_num];
- if (!is_unicode_wspace(chr->c))
- break;
- }
- *char_num_ptr = char_num;
-
- if (span != line->first_span || char_num >= span->len)
- return 0;
-
- /* Now we check for various special cases, which we consider to mean
- * that this is probably a list entry and therefore should always count
- * as a separate paragraph (and hence not be entered in the line height
- * table). */
- chr = &span->text[char_num];
-
- /* Is the first char on the line, a bullet point? */
- if (is_unicode_bullet(chr->c))
- return 1;
-
-#ifdef SPOT_LINE_NUMBERS
- /* Is the entire first span a number? Or does it start with a number
- * followed by ) or : ? Allow to involve single latin chars too. */
- if (is_number(chr->c) || is_latin_char(chr->c))
- {
- int cn = char_num;
- int met_char = is_latin_char(chr->c);
- for (cn = char_num+1; cn < span->len; cn++)
- {
- fz_text_char *chr2 = &span->text[cn];
-
- if (is_latin_char(chr2->c) && !met_char)
- {
- met_char = 1;
- continue;
- }
- met_char = 0;
- if (!is_number(chr2->c) && !is_unicode_wspace(chr2->c))
- break;
- else if (chr2->c == ')' || chr2->c == ':')
- {
- cn = span->len;
- break;
- }
- }
- if (cn == span->len)
- return 1;
- }
-
- /* Is the entire first span a roman numeral? Or does it start with
- * a roman numeral followed by ) or : ? */
- if (is_roman(chr->c))
- {
- int cn = char_num;
- for (cn = char_num+1; cn < span->len; cn++)
- {
- fz_text_char *chr2 = &span->text[cn];
-
- if (!is_roman(chr2->c) && !is_unicode_wspace(chr2->c))
- break;
- else if (chr2->c == ')' || chr2->c == ':')
- {
- cn = span->len;
- break;
- }
- }
- if (cn == span->len)
- return 1;
- }
-#endif
- return 0;
-}
-
-typedef struct region_masks_s region_masks;
-
-typedef struct region_mask_s region_mask;
-
-typedef struct region_s region;
-
-struct region_s
-{
- float start;
- float stop;
- float ave_start;
- float ave_stop;
- int align;
- float colw;
-};
-
-struct region_mask_s
-{
- fz_context *ctx;
- int freq;
- fz_point blv;
- int cap;
- int len;
- float size;
- region *mask;
-};
-
-struct region_masks_s
-{
- fz_context *ctx;
- int cap;
- int len;
- region_mask **mask;
-};
-
-static region_masks *
-new_region_masks(fz_context *ctx)
-{
- region_masks *rms = fz_malloc_struct(ctx, region_masks);
- rms->ctx = ctx;
- rms->cap = 0;
- rms->len = 0;
- rms->mask = NULL;
- return rms;
-}
-
-static void
-free_region_mask(region_mask *rm)
-{
- if (!rm)
- return;
- fz_free(rm->ctx, rm->mask);
- fz_free(rm->ctx, rm);
-}
-
-static void
-free_region_masks(region_masks *rms)
-{
- int i;
-
- if (!rms)
- return;
- for (i=0; i < rms->len; i++)
- {
- free_region_mask(rms->mask[i]);
- }
- fz_free(rms->ctx, rms->mask);
- fz_free(rms->ctx, rms);
-}
-
-static int region_masks_mergeable(const region_mask *rm1, const region_mask *rm2, float *score)
-{
- int i1, i2;
- int count = 0;
-
- *score = 0;
- if (fabsf(rm1->blv.x-rm2->blv.x) >= MY_EPSILON || fabsf(rm1->blv.y-rm2->blv.y) >= MY_EPSILON)
- return 0;
-
- for (i1 = 0, i2 = 0; i1 < rm1->len && i2 < rm2->len; )
- {
- if (rm1->mask[i1].stop < rm2->mask[i2].start)
- {
- /* rm1's region is entirely before rm2's */
- *score += rm1->mask[i1].stop - rm1->mask[i1].start;
- i1++;
- }
- else if (rm1->mask[i1].start > rm2->mask[i2].stop)
- {
- /* rm2's region is entirely before rm1's */
- *score += rm2->mask[i2].stop - rm2->mask[i2].start;
- i2++;
- }
- else
- {
- float lscore, rscore;
- if (rm1->mask[i1].start < rm2->mask[i2].start)
- {
- if (i2 > 0 && rm2->mask[i2-1].stop >= rm1->mask[i1].start)
- return 0; /* Not compatible */
- lscore = rm2->mask[i2].start - rm1->mask[i1].start;
- }
- else
- {
- if (i1 > 0 && rm1->mask[i1-1].stop >= rm2->mask[i2].start)
- return 0; /* Not compatible */
- lscore = rm1->mask[i1].start - rm2->mask[i2].start;
- }
- if (rm1->mask[i1].stop > rm2->mask[i2].stop)
- {
- if (i2+1 < rm2->len && rm2->mask[i2+1].start <= rm1->mask[i1].stop)
- return 0; /* Not compatible */
- rscore = rm1->mask[i1].stop - rm2->mask[i2].stop;
- }
- else
- {
- if (i1+1 < rm1->len && rm1->mask[i1+1].start <= rm2->mask[i2].stop)
- return 0; /* Not compatible */
- rscore = rm2->mask[i2].stop - rm1->mask[i1].stop;
- }
- /* In order to allow a region to merge, either the
- * left, the right, or the centre must agree */
- if (lscore < 1)
- {
- if (rscore < 1)
- {
- rscore = 0;
- }
- lscore = 0;
- }
- else if (rscore < 1)
- {
- rscore = 0;
- }
- else
- {
- /* Neither Left or right agree. Does the centre? */
- float ave1 = rm1->mask[i1].start + rm1->mask[i1].stop;
- float ave2 = rm2->mask[i2].start + rm2->mask[i2].stop;
- if (fabsf(ave1-ave2) > 1)
- {
- /* Nothing agrees, so don't merge */
- return 0;
- }
- lscore = 0;
- rscore = 0;
- }
- *score += lscore + rscore;
- /* These two regions could be merged */
- i1++;
- i2++;
- }
- count++;
- }
- count += rm1->len-i1 + rm2->len-i2;
- return count;
-}
-
-static int region_mask_matches(const region_mask *rm1, const region_mask *rm2, float *score)
-{
- int i1, i2;
- int close = 1;
-
- *score = 0;
- if (fabsf(rm1->blv.x-rm2->blv.x) >= MY_EPSILON || fabsf(rm1->blv.y-rm2->blv.y) >= MY_EPSILON)
- return 0;
-
- for (i1 = 0, i2 = 0; i1 < rm1->len && i2 < rm2->len; )
- {
- if (rm1->mask[i1].stop < rm2->mask[i2].start)
- {
- /* rm1's region is entirely before rm2's */
- *score += rm1->mask[i1].stop - rm1->mask[i1].start;
- i1++;
- }
- else if (rm1->mask[i1].start > rm2->mask[i2].stop)
- {
- /* Not compatible */
- return 0;
- }
- else
- {
- float lscore, rscore;
- if (rm1->mask[i1].start > rm2->mask[i2].start)
- {
- /* Not compatible */
- return 0;
- }
- if (rm1->mask[i1].stop < rm2->mask[i2].stop)
- {
- /* Not compatible */
- return 0;
- }
- lscore = rm2->mask[i2].start - rm1->mask[i1].start;
- rscore = rm1->mask[i1].stop - rm2->mask[i2].stop;
- if (lscore < 1)
- {
- if (rscore < 1)
- close++;
- close++;
- }
- else if (rscore < 1)
- close++;
- else if (fabsf(lscore - rscore) < 1)
- {
- lscore = fabsf(lscore-rscore);
- rscore = 0;
- close++;
- }
- *score += lscore + rscore;
- i1++;
- i2++;
- }
- }
- if (i1 < rm1->len)
- {
- /* Still more to go in rm1 */
- if (rm1->mask[i1].start < rm2->mask[rm2->len-1].stop)
- return 0;
- }
- else if (i2 < rm2->len)
- {
- /* Still more to go in rm2 */
- if (rm2->mask[i2].start < rm1->mask[rm1->len-1].stop)
- return 0;
- }
-
- return close;
-}
-
-static void region_mask_merge(region_mask *rm1, const region_mask *rm2, int newlen)
-{
- int o, i1, i2;
-
- /* First, ensure that rm1 is long enough */
- if (rm1->cap < newlen)
- {
- int newcap = rm1->cap ? rm1->cap : 2;
- do
- {
- newcap *= 2;
- }
- while (newcap < newlen);
- rm1->mask = fz_resize_array(rm1->ctx, rm1->mask, newcap, sizeof(*rm1->mask));
- rm1->cap = newcap;
- }
-
- /* Now run backwards along rm1, filling it out with the merged regions */
- for (o = newlen-1, i1 = rm1->len-1, i2 = rm2->len-1; o >= 0; o--)
- {
- /* So we read from i1 and i2 and store in o */
- if (i1 < 0)
- {
- /* Just copy i2 */
- rm1->mask[o] = rm2->mask[i2];
- i2--;
- }
- else if (i2 < 0)
- {
- /* Just copy i1 */
- rm1->mask[o] = rm1->mask[i1];
- i1--;
- }
- else if (rm1->mask[i1].stop < rm2->mask[i2].start)
- {
- /* rm1's region is entirely before rm2's - copy rm2's */
- rm1->mask[o] = rm2->mask[i2];
- i2--;
- }
- else if (rm2->mask[i2].stop < rm1->mask[i1].start)
- {
- /* rm2's region is entirely before rm1's - copy rm1's */
- rm1->mask[o] = rm1->mask[i1];
- i1--;
- }
- else
- {
- /* We must be merging */
- rm1->mask[o].ave_start = (rm1->mask[i1].start * rm1->freq + rm2->mask[i2].start * rm2->freq)/(rm1->freq + rm2->freq);
- rm1->mask[o].ave_stop = (rm1->mask[i1].stop * rm1->freq + rm2->mask[i2].stop * rm2->freq)/(rm1->freq + rm2->freq);
- rm1->mask[o].start = fz_min(rm1->mask[i1].start, rm2->mask[i2].start);
- rm1->mask[o].stop = fz_max(rm1->mask[i1].stop, rm2->mask[i2].stop);
- i1--;
- i2--;
- }
- }
- rm1->freq += rm2->freq;
- rm1->len = newlen;
-}
-
-static region_mask *region_masks_match(const region_masks *rms, const region_mask *rm, fz_text_line *line, region_mask *prev_match)
-{
- int i;
- float best_score = 9999999;
- float score;
- int best = -1;
- int best_count = 0;
-
- /* If the 'previous match' matches, use it regardless. */
- if (prev_match && region_mask_matches(prev_match, rm, &score))
- {
- return prev_match;
- }
-
- /* Run through and find the 'most compatible' region mask. We are
- * guaranteed that there will always be at least one compatible one!
- */
- for (i=0; i < rms->len; i++)
- {
- int count = region_mask_matches(rms->mask[i], rm, &score);
- if (count > best_count || (count == best_count && (score < best_score || best == -1)))
- {
- best = i;
- best_score = score;
- best_count = count;
- }
- }
- assert(best >= 0 && best < rms->len);
-
- /* So we have the matching mask. */
- return rms->mask[best];
-}
-
-#ifdef DEBUG_MASKS
-static void
-dump_region_mask(const region_mask *rm)
-{
- int j;
- for (j = 0; j < rm->len; j++)
- {
- printf("%g->%g ", rm->mask[j].start, rm->mask[j].stop);
- }
- printf("* %d\n", rm->freq);
-}
-
-static void
-dump_region_masks(const region_masks *rms)
-{
- int i;
-
- for (i = 0; i < rms->len; i++)
- {
- region_mask *rm = rms->mask[i];
- dump_region_mask(rm);
- }
-}
-#endif
-
-static void region_masks_add(region_masks *rms, region_mask *rm)
-{
- /* Add rm to rms */
- if (rms->len == rms->cap)
- {
- int newcap = (rms->cap ? rms->cap * 2 : 4);
- rms->mask = fz_resize_array(rms->ctx, rms->mask, newcap, sizeof(*rms->mask));
- rms->cap = newcap;
- }
- rms->mask[rms->len] = rm;
- rms->len++;
-}
-
-static void region_masks_sort(region_masks *rms)
-{
- int i, j;
-
- /* First calculate sizes */
- for (i=0; i < rms->len; i++)
- {
- region_mask *rm = rms->mask[i];
- float size = 0;
- for (j=0; j < rm->len; j++)
- {
- size += rm->mask[j].stop - rm->mask[j].start;
- }
- rm->size = size;
- }
-
- /* Now, sort on size */
- /* FIXME: bubble sort - use heapsort for efficiency */
- for (i=0; i < rms->len-1; i++)
- {
- for (j=i+1; j < rms->len; j++)
- {
- if (rms->mask[i]->size < rms->mask[j]->size)
- {
- region_mask *tmp = rms->mask[i];
- rms->mask[i] = rms->mask[j];
- rms->mask[j] = tmp;
- }
- }
- }
-}
-
-static void region_masks_merge(region_masks *rms, region_mask *rm)
-{
- int i;
- float best_score = 9999999;
- float score;
- int best = -1;
- int best_count = 0;
-
-#ifdef DEBUG_MASKS
- printf("\nAdding:\n");
- dump_region_mask(rm);
- printf("To:\n");
- dump_region_masks(rms);
-#endif
- for (i=0; i < rms->len; i++)
- {
- int count = region_masks_mergeable(rms->mask[i], rm, &score);
- if (count && (score < best_score || best == -1))
- {
- best = i;
- best_count = count;
- best_score = score;
- }
- }
- if (best != -1)
- {
- region_mask_merge(rms->mask[best], rm, best_count);
-#ifdef DEBUG_MASKS
- printf("Merges to give:\n");
- dump_region_masks(rms);
-#endif
- free_region_mask(rm);
- return;
- }
- region_masks_add(rms, rm);
-#ifdef DEBUG_MASKS
- printf("Adding new one to give:\n");
- dump_region_masks(rms);
-#endif
-}
-
-static region_mask *
-new_region_mask(fz_context *ctx, const fz_point *blv)
-{
- region_mask *rm = fz_malloc_struct(ctx, region_mask);
- rm->ctx = ctx;
- rm->freq = 1;
- rm->blv = *blv;
- rm->cap = 0;
- rm->len = 0;
- rm->mask = NULL;
- return rm;
-}
-
-static void
-region_mask_project(const region_mask *rm, const fz_point *min, const fz_point *max, float *start, float *end)
-{
- /* We project min and max down onto the blv */
- float s = min->x * rm->blv.x + min->y * rm->blv.y;
- float e = max->x * rm->blv.x + max->y * rm->blv.y;
- if (s > e)
- {
- *start = e;
- *end = s;
- }
- else
- {
- *start = s;
- *end = e;
- }
-}
-
-static void
-region_mask_add(region_mask *rm, const fz_point *min, const fz_point *max)
-{
- float start, end;
- int i, j;
-
- region_mask_project(rm, min, max, &start, &end);
-
- /* Now add start/end into our region list. Typically we will be adding
- * to the end of the region list, so search from there backwards. */
- for (i = rm->len; i > 0;)
- {
- if (start > rm->mask[i-1].stop)
- break;
- i--;
- }
- /* So we know that our interval can only affect list items >= i.
- * We know that start is after our previous end. */
- if (i == rm->len || end < rm->mask[i].start)
- {
- /* Insert new one. No overlap. No merging */
- if (rm->len == rm->cap)
- {
- int newcap = (rm->cap ? rm->cap * 2 : 4);
- rm->mask = fz_resize_array(rm->ctx, rm->mask, newcap, sizeof(*rm->mask));
- rm->cap = newcap;
- }
- if (rm->len > i)
- memmove(&rm->mask[i+1], &rm->mask[i], (rm->len - i) * sizeof(*rm->mask));
- rm->mask[i].ave_start = start;
- rm->mask[i].ave_stop = end;
- rm->mask[i].start = start;
- rm->mask[i].stop = end;
- rm->len++;
- }
- else
- {
- /* Extend current one down. */
- rm->mask[i].ave_start = start;
- rm->mask[i].start = start;
- if (rm->mask[i].stop < end)
- {
- rm->mask[i].stop = end;
- rm->mask[i].ave_stop = end;
- /* Our region may now extend upwards too far */
- i++;
- j = i;
- while (j < rm->len && rm->mask[j].start <= end)
- {
- rm->mask[i-1].stop = end = rm->mask[j].stop;
- j++;
- }
- if (i != j)
- {
- /* Move everything from j down to i */
- while (j < rm->len)
- {
- rm->mask[i++] = rm->mask[j++];
- }
- }
- rm->len -= j-i;
- }
- }
-}
-
-static int
-region_mask_column(region_mask *rm, const fz_point *min, const fz_point *max, int *align, float *colw, float *left_)
-{
- float start, end, left, right;
- int i;
-
- region_mask_project(rm, min, max, &start, &end);
-
- for (i = 0; i < rm->len; i++)
- {
- /* The use of MY_EPSILON here is because we might be matching
- * start/end values calculated with slightly different blv's */
- if (rm->mask[i].start - MY_EPSILON <= start && rm->mask[i].stop + MY_EPSILON >= end)
- break;
- }
- if (i >= rm->len)
- {
- *align = 0;
- *colw = 0;
- return 0;
- }
- left = start - rm->mask[i].start;
- right = rm->mask[i].stop - end;
- if (left < 1 && right < 1)
- *align = rm->mask[i].align;
- else if (left*2 <= right)
- *align = 0; /* Left */
- else if (right * 2 < left)
- *align = 2; /* Right */
- else
- *align = 1;
- *left_ = left;
- *colw = rm->mask[i].colw;
- return i;
-}
-
-static void
-region_mask_alignment(region_mask *rm)
-{
- int i;
- float width = 0;
-
- for (i = 0; i < rm->len; i++)
- {
- width += rm->mask[i].stop - rm->mask[i].start;
- }
- for (i = 0; i < rm->len; i++)
- {
- region *r = &rm->mask[i];
- float left = r->ave_start - r->start;
- float right = r->stop - r->ave_stop;
- if (left*2 <= right)
- r->align = 0; /* Left */
- else if (right * 2 < left)
- r->align = 2; /* Right */
- else
- r->align = 1;
- r->colw = 100 * (rm->mask[i].stop - rm->mask[i].start) / width;
- }
-}
-
-static void
-region_masks_alignment(region_masks *rms)
-{
- int i;
-
- for (i = 0; i < rms->len; i++)
- {
- region_mask_alignment(rms->mask[i]);
- }
-}
-
-static int
-is_unicode_hyphen(int c)
-{
- /* We omit 0x2011 (Non breaking hyphen) and 0x2043 (Hyphen Bullet)
- * from this list. */
- return (c == '-' ||
- c == 0x2010 || /* Hyphen */
- c == 0x002d || /* Hyphen-Minus */
- c == 0x00ad || /* Soft hyphen */
- c == 0x058a || /* Armenian Hyphen */
- c == 0x1400 || /* Canadian Syllabive Hyphen */
- c == 0x1806); /* Mongolian Todo soft hyphen */
-}
-
-static int
-is_unicode_hyphenatable(int c)
-{
- /* This is a pretty ad-hoc collection. It may need tuning. */
- return ((c >= 'A' && c <= 'Z') ||
- (c >= 'a' && c <= 'z') ||
- (c >= 0x00c0 && c <= 0x00d6) ||
- (c >= 0x00d8 && c <= 0x00f6) ||
- (c >= 0x00f8 && c <= 0x02af) ||
- (c >= 0x1d00 && c <= 0x1dbf) ||
- (c >= 0x1e00 && c <= 0x1eff) ||
- (c >= 0x2c60 && c <= 0x2c7f) ||
- (c >= 0xa722 && c <= 0xa78e) ||
- (c >= 0xa790 && c <= 0xa793) ||
- (c >= 0xa7a8 && c <= 0xa7af) ||
- (c >= 0xfb00 && c <= 0xfb07) ||
- (c >= 0xff21 && c <= 0xff3a) ||
- (c >= 0xff41 && c <= 0xff5a));
-}
-
-static void
-dehyphenate(fz_text_span *s1, fz_text_span *s2)
-{
- int i;
-
- for (i = s1->len-1; i > 0; i--)
- if (!is_unicode_wspace(s1->text[i].c))
- break;
- /* Can't leave an empty span. */
- if (i == 0)
- return;
-
- if (!is_unicode_hyphen(s1->text[i].c))
- return;
- if (!is_unicode_hyphenatable(s1->text[i-1].c))
- return;
- if (!is_unicode_hyphenatable(s2->text[0].c))
- return;
- s1->len = i;
- s2->spacing = 0;
-}
-
-void
-fz_analyze_text(fz_context *ctx, fz_text_sheet *sheet, fz_text_page *page)
-{
- fz_text_line *line;
- fz_text_span *span;
- line_heights *lh;
- region_masks *rms;
- int block_num;
-
- /* Simple paragraph analysis; look for the most common 'inter line'
- * spacing. This will be assumed to be our line spacing. Anything
- * more than 25% wider than this will be assumed to be a paragraph
- * space. */
-
- /* Step 1: Gather the line height information */
- lh = new_line_heights(ctx);
- for (block_num = 0; block_num < page->len; block_num++)
- {
- fz_text_block *block;
-
- if (page->blocks[block_num].type != FZ_PAGE_BLOCK_TEXT)
- continue;
- block = page->blocks[block_num].u.text;
-
- for (line = block->lines; line < block->lines + block->len; line++)
- {
- /* For every style in the line, add lineheight to the
- * record for that style. FIXME: This is a nasty n^2
- * algorithm at the moment. */
- fz_text_style *style = NULL;
-
- if (line->distance == 0)
- continue;
-
- for (span = line->first_span; span; span = span->next)
- {
- int char_num;
-
- if (is_list_entry(line, span, &char_num))
- goto list_entry;
-
- for (; char_num < span->len; char_num++)
- {
- fz_text_char *chr = &span->text[char_num];
-
- /* Ignore any whitespace chars */
- if (is_unicode_wspace(chr->c))
- continue;
-
- if (chr->style != style)
- {
- /* Have we had this style before? */
- int match = 0;
- fz_text_span *span2;
- for (span2 = line->first_span; span2; span2 = span2->next)
- {
- int char_num2;
- for (char_num2 = 0; char_num2 < span2->len; char_num2++)
- {
- fz_text_char *chr2 = &span2->text[char_num2];
- if (chr2->style == chr->style)
- {
- match = 1;
- break;
- }
- }
- }
- if (char_num > 0 && match == 0)
- {
- fz_text_span *span2 = span;
- int char_num2;
- for (char_num2 = 0; char_num2 < char_num; char_num2++)
- {
- fz_text_char *chr2 = &span2->text[char_num2];
- if (chr2->style == chr->style)
- {
- match = 1;
- break;
- }
- }
- }
- if (match == 0)
- insert_line_height(lh, chr->style, line->distance);
- style = chr->style;
- }
- }
-list_entry:
- {}
- }
- }
- }
-
- /* Step 2: Find the most popular line height for each style */
- cull_line_heights(lh);
-
- /* Step 3: Run through the blocks, breaking each block into two if
- * the line height isn't right. */
- for (block_num = 0; block_num < page->len; block_num++)
- {
- int line_num;
- fz_text_block *block;
-
- if (page->blocks[block_num].type != FZ_PAGE_BLOCK_TEXT)
- continue;
- block = page->blocks[block_num].u.text;
-
- for (line_num = 0; line_num < block->len; line_num++)
- {
- /* For every style in the line, check to see if lineheight
- * is correct for that style. FIXME: We check each style
- * more than once, currently. */
- int ok = 0; /* -1 = early exit, split now. 0 = split. 1 = don't split. */
- fz_text_style *style = NULL;
- line = &block->lines[line_num];
-
- if (line->distance == 0)
- continue;
-
-#ifdef DEBUG_LINE_HEIGHTS
- printf("line height=%g nspans=%d\n", line->distance, line->len);
-#endif
- for (span = line->first_span; span; span = span->next)
- {
- int char_num;
-
- if (is_list_entry(line, span, &char_num))
- goto force_paragraph;
-
- /* Now we do the rest of the line */
- for (; char_num < span->len; char_num++)
- {
- fz_text_char *chr = &span->text[char_num];
-
- /* Ignore any whitespace chars */
- if (is_unicode_wspace(chr->c))
- continue;
-
- if (chr->style != style)
- {
- float proper_step = line_height_for_style(lh, chr->style);
- if (proper_step * 0.95 <= line->distance && line->distance <= proper_step * 1.05)
- {
- ok = 1;
- break;
- }
- style = chr->style;
- }
- }
- if (ok)
- break;
- }
- if (!ok)
- {
-force_paragraph:
- split_block(ctx, page, block_num, line_num);
- break;
- }
- }
- }
- free_line_heights(lh);
-
- /* Simple line region analysis:
- * For each line:
- * form a list of 'start/stop' points (henceforth a 'region mask')
- * find the normalised baseline vector for the line.
- * Store the region mask and baseline vector.
- * Collate lines that have compatible region masks and identical
- * baseline vectors.
- * If the collated masks are column-like, then split into columns.
- * Otherwise split into tables.
- */
- rms = new_region_masks(ctx);
-
- /* Step 1: Form the region masks and store them into a list with the
- * normalised baseline vectors. */
- for (block_num = 0; block_num < page->len; block_num++)
- {
- fz_text_block *block;
-
- if (page->blocks[block_num].type != FZ_PAGE_BLOCK_TEXT)
- continue;
- block = page->blocks[block_num].u.text;
-
- for (line = block->lines; line < block->lines + block->len; line++)
- {
- fz_point blv;
- region_mask *rm;
-
-#ifdef DEBUG_MASKS
- printf("Line: ");
- dump_line(line);
-#endif
- blv = line->first_span->max;
- blv.x -= line->first_span->min.x;
- blv.y -= line->first_span->min.y;
- fz_normalize_vector(&blv);
-
- rm = new_region_mask(ctx, &blv);
- for (span = line->first_span; span; span = span->next)
- {
- fz_point *region_min = &span->min;
- fz_point *region_max = &span->max;
-
- /* Treat adjacent spans as one big region */
- while (span->next && span->next->spacing < 1.5)
- {
- span = span->next;
- region_max = &span->max;
- }
-
- region_mask_add(rm, region_min, region_max);
- }
-#ifdef DEBUG_MASKS
- dump_region_mask(rm);
-#endif
- region_masks_add(rms, rm);
- }
- }
-
- /* Step 2: Sort the region_masks by size of masked region */
- region_masks_sort(rms);
-
-#ifdef DEBUG_MASKS
- printf("Sorted list of regions:\n");
- dump_region_masks(rms);
-#endif
- /* Step 3: Merge the region masks where possible (large ones first) */
- {
- int i;
- region_masks *rms2;
- rms2 = new_region_masks(ctx);
- for (i=0; i < rms->len; i++)
- {
- region_mask *rm = rms->mask[i];
- rms->mask[i] = NULL;
- region_masks_merge(rms2, rm);
- }
- free_region_masks(rms);
- rms = rms2;
- }
-
-#ifdef DEBUG_MASKS
- printf("Merged list of regions:\n");
- dump_region_masks(rms);
-#endif
-
- /* Step 4: Figure out alignment */
- region_masks_alignment(rms);
-
- /* Step 5: At this point, we should probably look at the region masks
- * to try to guess which ones represent columns on the page. With our
- * current code, we could only get blocks of lines that span 2 or more
- * columns if the PDF producer wrote text out horizontally across 2
- * or more columns, and we've never seen that (yet!). So we skip this
- * step for now. */
-
- /* Step 6: Run through the lines again, deciding which ones fit into
- * which region mask. */
- {
- region_mask *prev_match = NULL;
- for (block_num = 0; block_num < page->len; block_num++)
- {
- fz_text_block *block;
-
- if (page->blocks[block_num].type != FZ_PAGE_BLOCK_TEXT)
- continue;
- block = page->blocks[block_num].u.text;
-
- for (line = block->lines; line < block->lines + block->len; line++)
- {
- fz_point blv;
- region_mask *rm;
- region_mask *match;
-
- blv = line->first_span->max;
- blv.x -= line->first_span->min.x;
- blv.y -= line->first_span->min.y;
- fz_normalize_vector(&blv);
-
-#ifdef DEBUG_MASKS
- dump_line(line);
-#endif
- rm = new_region_mask(ctx, &blv);
- for (span = line->first_span; span; span = span->next)
- {
- fz_point *region_min = &span->min;
- fz_point *region_max = &span->max;
-
- /* Treat adjacent spans as one big region */
- while (span->next && span->next->spacing < 1.5)
- {
- span = span->next;
- region_max = &span->max;
- }
-
- region_mask_add(rm, region_min, region_max);
- }
-#ifdef DEBUG_MASKS
- printf("Mask: ");
- dump_region_mask(rm);
-#endif
- match = region_masks_match(rms, rm, line, prev_match);
- prev_match = match;
-#ifdef DEBUG_MASKS
- printf("Matches: ");
- dump_region_mask(match);
-#endif
- free_region_mask(rm);
- span = line->first_span;
- while (span)
- {
- fz_point *region_min = &span->min;
- fz_point *region_max = &span->max;
- fz_text_span *sn;
- int col, align;
- float colw, left;
-
- /* Treat adjacent spans as one big region */
-#ifdef DEBUG_ALIGN
- dump_span(span);
-#endif
- for (sn = span->next; sn && sn->spacing < 1.5; sn = sn->next)
- {
- region_max = &sn->max;
-#ifdef DEBUG_ALIGN
- dump_span(sn);
-#endif
- }
- col = region_mask_column(match, region_min, region_max, &align, &colw, &left);
-#ifdef DEBUG_ALIGN
- printf(" = col%d colw=%g align=%d\n", col, colw, align);
-#endif
- do
- {
- span->column = col;
- span->align = align;
- span->indent = left;
- span->column_width = colw;
- span = span->next;
- }
- while (span != sn);
-
- if (span)
- span = span->next;
- }
- line->region = match;
- }
- }
- free_region_masks(rms);
- }
-
- /* Step 7: Collate lines within a block that share the same region
- * mask. */
- for (block_num = 0; block_num < page->len; block_num++)
- {
- int line_num;
- int prev_line_num;
-
- fz_text_block *block;
-
- if (page->blocks[block_num].type != FZ_PAGE_BLOCK_TEXT)
- continue;
- block = page->blocks[block_num].u.text;
-
- /* First merge lines. This may leave empty lines behind. */
- for (prev_line_num = 0, line_num = 1; line_num < block->len; line_num++)
- {
- fz_text_line *prev_line;
- line = &block->lines[line_num];
- if (!line->first_span)
- continue;
- prev_line = &block->lines[prev_line_num];
- if (prev_line->region == line->region)
- {
- /* We only merge lines if the second line
- * only uses 1 of the columns. */
- int col = line->first_span->column;
- /* Copy the left value for the first span
- * in the first column in this line forward
- * for all the rest of the spans in the same
- * column. */
- float indent = line->first_span->indent;
- for (span = line->first_span->next; span; span = span->next)
- {
- if (col != span->column)
- break;
- span->indent = indent;
- }
- if (span)
- {
- prev_line_num = line_num;
- continue;
- }
-
- /* Merge line into prev_line */
- {
- fz_text_span **prev_line_span = &prev_line->first_span;
- int try_dehyphen = -1;
- fz_text_span *prev_span = NULL;
- span = line->first_span;
- while (span)
- {
- /* Skip forwards through the original
- * line, until we find a place where
- * span should go. */
- if ((*prev_line_span)->column <= span->column)
- {
- /* The current span we are considering
- * in prev_line is earlier than span.
- * Just skip forwards in prev_line. */
- prev_span = (*prev_line_span);
- prev_line_span = &prev_span->next;
- try_dehyphen = span->column;
- }
- else
- {
- /* We want to copy span into prev_line. */
- fz_text_span *next = (*prev_line_span)->next;
-
- if (prev_line_span == &prev_line->first_span)
- prev_line->first_span = span;
- if (next == NULL)
- prev_line->last_span = span;
- if (try_dehyphen == span->column)
- dehyphenate(prev_span, span);
- try_dehyphen = -1;
- prev_span = *prev_line_span = span;
- span = span->next;
- (*prev_line_span)->next = next;
- prev_line_span = &span->next;
- }
- }
- while (span || *prev_line_span);
- line->first_span = NULL;
- line->last_span = NULL;
- }
- }
- else
- prev_line_num = line_num;
- }
-
- /* Now get rid of the empty lines */
- for (prev_line_num = 0, line_num = 0; line_num < block->len; line_num++)
- {
- line = &block->lines[line_num];
- if (line->first_span)
- block->lines[prev_line_num++] = *line;
- }
- block->len = prev_line_num;
-
- /* Now try to spot indents */
- for (line_num = 0; line_num < block->len; line_num++)
- {
- fz_text_span *span_num, *sn;
- int col, count;
- line = &block->lines[line_num];
-
- /* Run through the spans... */
- span_num = line->first_span;
- {
- float indent = 0;
- /* For each set of spans that share the same
- * column... */
- col = span_num->column;
-#ifdef DEBUG_INDENTS
- printf("Indent %g: ", span_num->indent);
- dump_span(span_num);
- printf("\n");
-#endif
-
- /* find the average indent of all but the first.. */
- for (sn = span_num->next, count = 0; sn && sn->column == col; sn = sn->next, count++)
- {
-#ifdef DEBUG_INDENTS
- printf("Indent %g: ", sn->indent);
- dump_span(sn);
- printf("\n");
-#endif
- indent += sn->indent;
- sn->indent = 0;
- }
- if (sn != span_num->next)
- indent /= count;
-
- /* And compare this indent with the first one... */
-#ifdef DEBUG_INDENTS
- printf("Average indent %g ", indent);
-#endif
- indent -= span_num->indent;
-#ifdef DEBUG_INDENTS
- printf("delta %g ", indent);
-#endif
- if (fabsf(indent) < 1)
- {
- /* No indent worth speaking of */
- indent = 0;
- }
-#ifdef DEBUG_INDENTS
- printf("recorded %g\n", indent);
-#endif
- span_num->indent = indent;
- span_num = sn;
- }
- for (; span_num; span_num = span_num->next)
- {
- span_num->indent = 0;
- }
- }
- }
-}
diff --git a/fitz/text_search.c b/fitz/text_search.c
deleted file mode 100644
index f1f0d203..00000000
--- a/fitz/text_search.c
+++ /dev/null
@@ -1,279 +0,0 @@
-#include "mupdf/fitz.h"
-
-static inline int fz_tolower(int c)
-{
- /* TODO: proper unicode case folding */
- if (c >= 'A' && c <= 'Z')
- return c - 'A' + 'a';
- return c;
-}
-
-static inline int iswhite(int c)
-{
- return c == ' ' || c == '\r' || c == '\n' || c == '\t';
-}
-
-fz_char_and_box *fz_text_char_at(fz_char_and_box *cab, fz_text_page *page, int idx)
-{
- int block_num;
- int ofs = 0;
-
- for (block_num = 0; block_num < page->len; block_num++)
- {
- fz_text_block *block;
- fz_text_line *line;
- fz_text_span *span;
-
- if (page->blocks[block_num].type != FZ_PAGE_BLOCK_TEXT)
- continue;
- block = page->blocks[block_num].u.text;
- for (line = block->lines; line < block->lines + block->len; line++)
- {
- for (span = line->first_span; span; span = span->next)
- {
- if (idx < ofs + span->len)
- {
- cab->c = span->text[idx - ofs].c;
- fz_text_char_bbox(&cab->bbox, span, idx - ofs);
- return cab;
- }
- ofs += span->len;
- }
- /* pseudo-newline */
- if (idx == ofs)
- {
- cab->bbox = fz_empty_rect;
- cab->c = ' ';
- return cab;
- }
- ofs++;
- }
- }
- cab->bbox = fz_empty_rect;
- cab->c = 0;
- return cab;
-}
-
-static int charat(fz_text_page *page, int idx)
-{
- fz_char_and_box cab;
- return fz_text_char_at(&cab, page, idx)->c;
-}
-
-static fz_rect *bboxat(fz_text_page *page, int idx, fz_rect *bbox)
-{
- fz_char_and_box cab;
- /* FIXME: Nasty extra copy */
- *bbox = fz_text_char_at(&cab, page, idx)->bbox;
- return bbox;
-}
-
-static int textlen(fz_text_page *page)
-{
- int len = 0;
- int block_num;
-
- for (block_num = 0; block_num < page->len; block_num++)
- {
- fz_text_block *block;
- fz_text_line *line;
- fz_text_span *span;
-
- if (page->blocks[block_num].type != FZ_PAGE_BLOCK_TEXT)
- continue;
- block = page->blocks[block_num].u.text;
- for (line = block->lines; line < block->lines + block->len; line++)
- {
- for (span = line->first_span; span; span = span->next)
- {
- len += span->len;
- }
- len++; /* pseudo-newline */
- }
- }
- return len;
-}
-
-static int match(fz_text_page *page, const char *s, int n)
-{
- int orig = n;
- int c;
- while (*s)
- {
- s += fz_chartorune(&c, (char *)s);
- if (iswhite(c) && iswhite(charat(page, n)))
- {
- const char *s_next;
-
- /* Skip over whitespace in the document */
- do
- n++;
- while (iswhite(charat(page, n)));
-
- /* Skip over multiple whitespace in the search string */
- while (s_next = s + fz_chartorune(&c, (char *)s), iswhite(c))
- s = s_next;
- }
- else
- {
- if (fz_tolower(c) != fz_tolower(charat(page, n)))
- return 0;
- n++;
- }
- }
- return n - orig;
-}
-
-int
-fz_search_text_page(fz_context *ctx, fz_text_page *text, const char *needle, fz_rect *hit_bbox, int hit_max)
-{
- int pos, len, i, n, hit_count;
-
- if (strlen(needle) == 0)
- return 0;
-
- hit_count = 0;
- len = textlen(text);
- for (pos = 0; pos < len; pos++)
- {
- n = match(text, needle, pos);
- if (n)
- {
- fz_rect linebox = fz_empty_rect;
- for (i = 0; i < n; i++)
- {
- fz_rect charbox;
- bboxat(text, pos + i, &charbox);
- if (!fz_is_empty_rect(&charbox))
- {
- if (charbox.y0 != linebox.y0 || fz_abs(charbox.x0 - linebox.x1) > 5)
- {
- if (!fz_is_empty_rect(&linebox) && hit_count < hit_max)
- hit_bbox[hit_count++] = linebox;
- linebox = charbox;
- }
- else
- {
- fz_union_rect(&linebox, &charbox);
- }
- }
- }
- if (!fz_is_empty_rect(&linebox) && hit_count < hit_max)
- hit_bbox[hit_count++] = linebox;
- }
- }
-
- return hit_count;
-}
-
-int
-fz_highlight_selection(fz_context *ctx, fz_text_page *page, fz_rect rect, fz_rect *hit_bbox, int hit_max)
-{
- fz_rect linebox, charbox;
- fz_text_block *block;
- fz_text_line *line;
- fz_text_span *span;
- int i, block_num, hit_count;
-
- float x0 = rect.x0;
- float x1 = rect.x1;
- float y0 = rect.y0;
- float y1 = rect.y1;
-
- hit_count = 0;
-
- for (block_num = 0; block_num < page->len; block_num++)
- {
- if (page->blocks[block_num].type != FZ_PAGE_BLOCK_TEXT)
- continue;
- block = page->blocks[block_num].u.text;
- for (line = block->lines; line < block->lines + block->len; line++)
- {
- linebox = fz_empty_rect;
- for (span = line->first_span; span; span = span->next)
- {
- for (i = 0; i < span->len; i++)
- {
- fz_text_char_bbox(&charbox, span, i);
- if (charbox.x1 >= x0 && charbox.x0 <= x1 && charbox.y1 >= y0 && charbox.y0 <= y1)
- {
- if (charbox.y0 != linebox.y0 || fz_abs(charbox.x0 - linebox.x1) > 5)
- {
- if (!fz_is_empty_rect(&linebox) && hit_count < hit_max)
- hit_bbox[hit_count++] = linebox;
- linebox = charbox;
- }
- else
- {
- fz_union_rect(&linebox, &charbox);
- }
- }
- }
- }
- if (!fz_is_empty_rect(&linebox) && hit_count < hit_max)
- hit_bbox[hit_count++] = linebox;
- }
- }
-
- return hit_count;
-}
-
-char *
-fz_copy_selection(fz_context *ctx, fz_text_page *page, fz_rect rect)
-{
- fz_buffer *buffer;
- fz_rect hitbox;
- int c, i, block_num, seen = 0;
- char *s;
-
- float x0 = rect.x0;
- float x1 = rect.x1;
- float y0 = rect.y0;
- float y1 = rect.y1;
-
- buffer = fz_new_buffer(ctx, 1024);
-
- for (block_num = 0; block_num < page->len; block_num++)
- {
- fz_text_block *block;
- fz_text_line *line;
- fz_text_span *span;
-
- if (page->blocks[block_num].type != FZ_PAGE_BLOCK_TEXT)
- continue;
- block = page->blocks[block_num].u.text;
- for (line = block->lines; line < block->lines + block->len; line++)
- {
- for (span = line->first_span; span; span = span->next)
- {
- if (seen)
- {
- fz_write_buffer_byte(ctx, buffer, '\n');
- }
-
- seen = 0;
-
- for (i = 0; i < span->len; i++)
- {
- fz_text_char_bbox(&hitbox, span, i);
- c = span->text[i].c;
- if (c < 32)
- c = '?';
- if (hitbox.x1 >= x0 && hitbox.x0 <= x1 && hitbox.y1 >= y0 && hitbox.y0 <= y1)
- {
- fz_write_buffer_rune(ctx, buffer, c);
- seen = 1;
- }
- }
-
- seen = (seen && span == line->last_span);
- }
- }
- }
-
- fz_write_buffer_byte(ctx, buffer, 0);
-
- s = (char*)buffer->data;
- fz_free(ctx, buffer);
- return s;
-}