summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2014-01-03 16:50:41 +0000
committerRobin Watts <robin.watts@artifex.com>2014-01-07 10:25:42 +0000
commit7f009acebb75ff88c1ee934b03fa2d15f7785b32 (patch)
tree7be547523d730d104c62e4b5d43685dd8bb5bd40
parent016adfa063293281a0896c62bf22e406b09ddf21 (diff)
downloadmupdf-7f009acebb75ff88c1ee934b03fa2d15f7785b32.tar.xz
Introduce 'document handlers'.
We define a document handler for each file type (2 in the case of PDF, one to handle files with the ability to 'run' them, and one without). We then register these handlers with the context at startup, and then call fz_open_document... as usual. This enables people to select the document types they want at will (and even to extend the library with more document types should they wish).
-rw-r--r--include/mupdf/fitz/context.h6
-rw-r--r--include/mupdf/fitz/document.h23
-rw-r--r--include/mupdf/fitz/system.h2
-rw-r--r--include/mupdf/pdf/document.h2
-rw-r--r--platform/win32/libmupdf.vcproj8
-rw-r--r--platform/x11/pdfapp.c2
-rw-r--r--scripts/cmapdump.c13
-rw-r--r--source/cbz/mucbz.c23
-rw-r--r--source/fitz/context.c4
-rw-r--r--source/fitz/document-all.c9
-rw-r--r--source/fitz/document-no-run.c9
-rw-r--r--source/fitz/document.c163
-rw-r--r--source/img/muimage.c31
-rw-r--r--source/pdf/pdf-xref-aux.c7
-rw-r--r--source/pdf/pdf-xref.c24
-rw-r--r--source/tools/mudraw.c2
-rw-r--r--source/xps/xps-doc.c25
17 files changed, 296 insertions, 57 deletions
diff --git a/include/mupdf/fitz/context.h b/include/mupdf/fitz/context.h
index bb171b3f..c6adbb3f 100644
--- a/include/mupdf/fitz/context.h
+++ b/include/mupdf/fitz/context.h
@@ -18,6 +18,7 @@ typedef struct fz_aa_context_s fz_aa_context;
typedef struct fz_locks_context_s fz_locks_context;
typedef struct fz_store_s fz_store;
typedef struct fz_glyph_cache_s fz_glyph_cache;
+typedef struct fz_document_handler_context_s fz_document_handler_context;
typedef struct fz_context_s fz_context;
struct fz_alloc_context_s
@@ -107,6 +108,7 @@ struct fz_context_s
fz_aa_context *aa;
fz_store *store;
fz_glyph_cache *glyph_cache;
+ fz_document_handler_context *handler;
};
/*
@@ -416,6 +418,10 @@ void fz_new_aa_context(fz_context *ctx);
void fz_free_aa_context(fz_context *ctx);
void fz_copy_aa_context(fz_context *dst, fz_context *src);
+void fz_new_document_handler_context(fz_context *ctx);
+void fz_drop_document_handler_context(fz_context *ctx);
+fz_document_handler_context *fz_keep_document_handler_context(fz_context *ctx);
+
/* Default allocator */
extern fz_alloc_context fz_alloc_default;
diff --git a/include/mupdf/fitz/document.h b/include/mupdf/fitz/document.h
index 887ca151..cda8870a 100644
--- a/include/mupdf/fitz/document.h
+++ b/include/mupdf/fitz/document.h
@@ -13,6 +13,7 @@
Document interface
*/
typedef struct fz_document_s fz_document;
+typedef struct fz_document_handler_s fz_document_handler;
typedef struct fz_page_s fz_page;
typedef struct fz_annot_s fz_annot;
@@ -60,6 +61,28 @@ struct fz_document_s
fz_document_rebind_fn *rebind;
};
+typedef fz_document *(fz_document_open_fn)(fz_context *ctx, const char *filename);
+typedef fz_document *(fz_document_open_with_stream_fn)(fz_context *ctx, fz_stream *stream);
+typedef int (fz_document_recognize_fn)(fz_context *ctx, const char *magic);
+
+struct fz_document_handler_s
+{
+ fz_document_recognize_fn *recognize;
+ fz_document_open_fn *open;
+ fz_document_open_with_stream_fn *open_with_stream;
+};
+
+extern fz_document_handler pdf_document_handler;
+extern fz_document_handler pdf_no_run_document_handler;
+extern fz_document_handler xps_document_handler;
+extern fz_document_handler cbz_document_handler;
+extern fz_document_handler img_document_handler;
+
+void fz_register_document_handler(fz_context *ctx, const fz_document_handler *handler);
+
+void fz_register_document_handlers(fz_context *ctx);
+void fz_register_no_run_document_handlers(fz_context *ctx);
+
/*
fz_open_document: Open a PDF, XPS or CBZ document.
diff --git a/include/mupdf/fitz/system.h b/include/mupdf/fitz/system.h
index 1decfda6..2f4868f2 100644
--- a/include/mupdf/fitz/system.h
+++ b/include/mupdf/fitz/system.h
@@ -355,4 +355,6 @@ static inline float my_atan2f(float o, float a)
#define atan2f(x,y) my_atan2f((x),(y))
#endif
+int fz_strcasecmp(const char *a, const char *b);
+
#endif
diff --git a/include/mupdf/pdf/document.h b/include/mupdf/pdf/document.h
index 73b3692d..8c71d88b 100644
--- a/include/mupdf/pdf/document.h
+++ b/include/mupdf/pdf/document.h
@@ -308,4 +308,6 @@ fz_device *pdf_page_write(pdf_document *doc, pdf_page *page);
void pdf_finish_edit(pdf_document *doc);
+int pdf_recognize(fz_context *doc, const char *magic);
+
#endif
diff --git a/platform/win32/libmupdf.vcproj b/platform/win32/libmupdf.vcproj
index 74f6df79..e8dc6fc6 100644
--- a/platform/win32/libmupdf.vcproj
+++ b/platform/win32/libmupdf.vcproj
@@ -434,6 +434,10 @@
>
</File>
<File
+ RelativePath="..\..\source\fitz\document-all.c"
+ >
+ </File>
+ <File
RelativePath="..\..\source\fitz\document.c"
>
</File>
@@ -989,6 +993,10 @@
>
</File>
<File
+ RelativePath="..\..\source\fitz\document-no-run.c"
+ >
+ </File>
+ <File
RelativePath="..\..\include\mupdf\fitz\document.h"
>
</File>
diff --git a/platform/x11/pdfapp.c b/platform/x11/pdfapp.c
index 10a44573..e9349526 100644
--- a/platform/x11/pdfapp.c
+++ b/platform/x11/pdfapp.c
@@ -192,6 +192,8 @@ void pdfapp_open_progressive(pdfapp_t *app, char *filename, int reload, int bps)
{
pdf_document *idoc;
+ fz_register_document_handlers(ctx);
+
#ifdef HAVE_CURL
if (!strncmp(filename, "http://", 7))
{
diff --git a/scripts/cmapdump.c b/scripts/cmapdump.c
index 88f1f800..a9e5de18 100644
--- a/scripts/cmapdump.c
+++ b/scripts/cmapdump.c
@@ -246,3 +246,16 @@ fz_glyph_cache *fz_keep_glyph_cache(fz_context *ctx)
{
return NULL;
}
+
+void fz_new_document_handler_context(fz_context *ctx)
+{
+}
+
+void fz_drop_document_handler_context(fz_context *ctx)
+{
+}
+
+fz_document_handler_context *fz_keep_document_handler_context(fz_context *ctx)
+{
+ return NULL;
+}
diff --git a/source/cbz/mucbz.c b/source/cbz/mucbz.c
index fa654a54..dc36e0be 100644
--- a/source/cbz/mucbz.c
+++ b/source/cbz/mucbz.c
@@ -430,3 +430,26 @@ cbz_init_document(cbz_document *doc)
doc->super.meta = (fz_document_meta_fn *)cbz_meta;
doc->super.rebind = (fz_document_rebind_fn *)cbz_rebind;
}
+
+static int
+cbz_recognize(fz_context *doc, const char *magic)
+{
+ char *ext = strrchr(magic, '.');
+
+ if (ext)
+ {
+ if (!fz_strcasecmp(ext, ".cbz") || !fz_strcasecmp(ext, ".zip"))
+ return 100;
+ }
+ if (!strcmp(magic, "cbz") || !strcmp(magic, "application/x-cbz"))
+ return 100;
+
+ return 0;
+}
+
+fz_document_handler cbz_document_handler =
+{
+ (fz_document_recognize_fn *)&cbz_recognize,
+ (fz_document_open_fn *)&cbz_open_document,
+ (fz_document_open_with_stream_fn *)&cbz_open_document_with_stream
+};
diff --git a/source/fitz/context.c b/source/fitz/context.c
index 72ea2d6a..d54e5b7d 100644
--- a/source/fitz/context.c
+++ b/source/fitz/context.c
@@ -49,6 +49,7 @@ fz_free_context(fz_context *ctx)
return;
/* Other finalisation calls go here (in reverse order) */
+ fz_drop_document_handler_context(ctx);
fz_drop_glyph_cache_context(ctx);
fz_drop_store_context(ctx);
fz_free_aa_context(ctx);
@@ -149,6 +150,7 @@ fz_new_context_imp(fz_alloc_context *alloc, fz_locks_context *locks, unsigned in
fz_new_colorspace_context(ctx);
fz_new_font_context(ctx);
fz_new_id_context(ctx);
+ fz_new_document_handler_context(ctx);
}
fz_catch(ctx)
{
@@ -195,6 +197,8 @@ fz_clone_context_internal(fz_context *ctx)
new_ctx->font = fz_keep_font_context(new_ctx);
new_ctx->id = ctx->id;
new_ctx->id = fz_keep_id_context(new_ctx);
+ new_ctx->handler = ctx->handler;
+ new_ctx->handler = fz_keep_document_handler_context(new_ctx);
return new_ctx;
}
diff --git a/source/fitz/document-all.c b/source/fitz/document-all.c
new file mode 100644
index 00000000..92b1c037
--- /dev/null
+++ b/source/fitz/document-all.c
@@ -0,0 +1,9 @@
+#include "mupdf/fitz.h"
+
+void fz_register_document_handlers(fz_context *ctx)
+{
+ fz_register_document_handler(ctx, &pdf_document_handler);
+ fz_register_document_handler(ctx, &xps_document_handler);
+ fz_register_document_handler(ctx, &cbz_document_handler);
+ fz_register_document_handler(ctx, &img_document_handler);
+}
diff --git a/source/fitz/document-no-run.c b/source/fitz/document-no-run.c
new file mode 100644
index 00000000..b0defe91
--- /dev/null
+++ b/source/fitz/document-no-run.c
@@ -0,0 +1,9 @@
+#include "mupdf/fitz.h"
+
+void fz_register_no_run_document_handlers(fz_context *ctx)
+{
+ fz_register_document_handler(ctx, &pdf_no_run_document_handler);
+ fz_register_document_handler(ctx, &xps_document_handler);
+ fz_register_document_handler(ctx, &cbz_document_handler);
+ fz_register_document_handler(ctx, &img_document_handler);
+}
diff --git a/source/fitz/document.c b/source/fitz/document.c
index a86c2f6e..d4838d0c 100644
--- a/source/fitz/document.c
+++ b/source/fitz/document.c
@@ -1,17 +1,66 @@
#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 int pdf_js_supported(void);
-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);
+enum
+{
+ FZ_DOCUMENT_HANDLER_MAX = 10
+};
-extern int pdf_js_supported(void);
+struct fz_document_handler_context_s
+{
+ int refs;
+ int count;
+ const fz_document_handler *handler[FZ_DOCUMENT_HANDLER_MAX];
+};
+
+void fz_new_document_handler_context(fz_context *ctx)
+{
+ ctx->handler = fz_malloc_struct(ctx, fz_document_handler_context);
+ ctx->handler->refs = 1;
+}
+
+fz_document_handler_context *fz_keep_document_handler_context(fz_context *ctx)
+{
+ if (!ctx || !ctx->handler)
+ return NULL;
+ ctx->handler->refs++;
+ return ctx->handler;
+}
+
+void fz_drop_document_handler_context(fz_context *ctx)
+{
+ if (!ctx || !ctx->handler)
+ return;
+
+ if (--ctx->handler->refs != 0)
+ return;
+
+ fz_free(ctx, ctx->handler);
+ ctx->handler = NULL;
+}
+
+void fz_register_document_handler(fz_context *ctx, const fz_document_handler *handler)
+{
+ fz_document_handler_context *dc;
+ int i;
+
+ if (!ctx || !handler)
+ return;
+
+ dc = ctx->handler;
+ if (dc == NULL)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Document handler list not found");
+
+ for (i = 0; i < dc->count; i++)
+ if (dc->handler[i] == handler)
+ return;
+
+ if (dc->count >= FZ_DOCUMENT_HANDLER_MAX)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "Too many document handlers");
+
+ dc->handler[dc->count++] = handler;
+}
static inline int fz_tolower(int c)
{
@@ -20,7 +69,7 @@ static inline int fz_tolower(int c)
return c;
}
-static inline int fz_strcasecmp(const char *a, const char *b)
+int fz_strcasecmp(const char *a, const char *b)
{
while (fz_tolower(*a) == fz_tolower(*b))
{
@@ -34,65 +83,65 @@ static inline int fz_strcasecmp(const char *a, const char *b)
fz_document *
fz_open_document_with_stream(fz_context *ctx, const char *magic, fz_stream *stream)
{
- char *ext = strrchr(magic, '.');
+ int i, score;
+ int best_i, best_score;
+ fz_document_handler_context *dc;
- if (ext)
+ if (ctx == NULL || magic == NULL || stream == NULL)
+ return NULL;
+
+ dc = ctx->handler;
+ if (dc->count == 0)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "No document handlers registered");
+
+ best_i = -1;
+ best_score = 0;
+ for (i = 0; i < dc->count; i++)
{
- 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);
+ score = dc->handler[i]->recognize(ctx, magic);
+ if (best_score < score)
+ {
+ best_score = score;
+ best_i = i;
+ }
}
- 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") ||
- !strcmp(magic, "application/oxps"))
- 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);
+ if (best_i >= 0)
+ return dc->handler[best_i]->open_with_stream(ctx, stream);
+
+ return NULL;
}
fz_document *
fz_open_document(fz_context *ctx, const char *filename)
{
- char *ext = strrchr(filename, '.');
+ int i, score;
+ int best_i, best_score;
+ fz_document_handler_context *dc;
+
+ if (ctx == NULL || filename == NULL)
+ return NULL;
+
+ dc = ctx->handler;
+ if (dc->count == 0)
+ fz_throw(ctx, FZ_ERROR_GENERIC, "No document handlers registered");
- if (ext)
+ best_i = -1;
+ best_score = 0;
+ for (i = 0; i < dc->count; i++)
{
- 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);
+ score = dc->handler[i]->recognize(ctx, filename);
+ if (best_score < score)
+ {
+ best_score = score;
+ best_i = i;
+ }
}
- /* last guess: pdf */
- return (fz_document*) pdf_open_document(ctx, filename);
+ if (best_i >= 0)
+ return dc->handler[best_i]->open(ctx, filename);
+
+ return NULL;
}
void
diff --git a/source/img/muimage.c b/source/img/muimage.c
index 26f4a0f3..300d6603 100644
--- a/source/img/muimage.c
+++ b/source/img/muimage.c
@@ -154,3 +154,34 @@ image_init_document(image_document *doc)
doc->super.meta = (fz_document_meta_fn *)image_meta;
doc->super.rebind = (fz_document_rebind_fn *)image_rebind;
}
+
+static int
+image_recognize(fz_context *doc, const char *magic)
+{
+ char *ext = strrchr(magic, '.');
+
+ if (ext)
+ {
+ 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 100;
+ }
+ 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 100;
+
+ return 0;
+}
+
+fz_document_handler img_document_handler =
+{
+ (fz_document_recognize_fn *)&image_recognize,
+ (fz_document_open_fn *)&image_open_document,
+ (fz_document_open_with_stream_fn *)&image_open_document_with_stream
+};
diff --git a/source/pdf/pdf-xref-aux.c b/source/pdf/pdf-xref-aux.c
index 968a8f9f..aac323de 100644
--- a/source/pdf/pdf-xref-aux.c
+++ b/source/pdf/pdf-xref-aux.c
@@ -27,3 +27,10 @@ pdf_open_document(fz_context *ctx, const char *filename)
doc->update_appearance = pdf_update_appearance;
return doc;
}
+
+fz_document_handler pdf_document_handler =
+{
+ (fz_document_recognize_fn *)&pdf_recognize,
+ (fz_document_open_fn *)&pdf_open_document,
+ (fz_document_open_with_stream_fn *)&pdf_open_document_with_stream
+};
diff --git a/source/pdf/pdf-xref.c b/source/pdf/pdf-xref.c
index d7c5cd1b..2afe4de8 100644
--- a/source/pdf/pdf-xref.c
+++ b/source/pdf/pdf-xref.c
@@ -1,4 +1,5 @@
#include "mupdf/pdf.h"
+#include "mupdf/fitz/document.h"
#undef DEBUG_PROGESSIVE_ADVANCE
@@ -2417,3 +2418,26 @@ pdf_document *pdf_create_document(fz_context *ctx)
}
return doc;
}
+
+int
+pdf_recognize(fz_context *doc, const char *magic)
+{
+ char *ext = strrchr(magic, '.');
+
+ if (ext)
+ {
+ if (!fz_strcasecmp(ext, ".pdf"))
+ return 100;
+ }
+ if (!strcmp(magic, "pdf") || !strcmp(magic, "application/pdf"))
+ return 100;
+
+ return 1;
+}
+
+fz_document_handler pdf_no_run_document_handler =
+{
+ (fz_document_recognize_fn *)&pdf_recognize,
+ (fz_document_open_fn *)&pdf_open_document_no_run,
+ (fz_document_open_with_stream_fn *)&pdf_open_document_no_run_with_stream
+};
diff --git a/source/tools/mudraw.c b/source/tools/mudraw.c
index 682aab86..914f6ba5 100644
--- a/source/tools/mudraw.c
+++ b/source/tools/mudraw.c
@@ -1193,6 +1193,8 @@ int main(int argc, char **argv)
fz_try(ctx)
{
+ fz_register_document_handlers(ctx);
+
while (fz_optind < argc)
{
fz_try(ctx)
diff --git a/source/xps/xps-doc.c b/source/xps/xps-doc.c
index 86d67d4a..af5bfe5a 100644
--- a/source/xps/xps-doc.c
+++ b/source/xps/xps-doc.c
@@ -531,3 +531,28 @@ xps_free_page(xps_document *doc, xps_page *page)
fz_free_xml(doc->ctx, page->root);
page->root = NULL;
}
+
+static int
+xps_recognize(fz_context *doc, const char *magic)
+{
+ char *ext = strrchr(magic, '.');
+
+ if (ext)
+ {
+ if (!fz_strcasecmp(ext, ".xps") || !fz_strcasecmp(ext, ".rels") || !fz_strcasecmp(ext, ".oxps"))
+ return 100;
+ }
+ if (!strcmp(magic, "xps") || !strcmp(magic, "oxps") ||
+ !strcmp(magic, "application/vnd.ms-xpsdocument") ||
+ !strcmp(magic, "application/oxps"))
+ return 100;
+
+ return 0;
+}
+
+fz_document_handler xps_document_handler =
+{
+ (fz_document_recognize_fn *)&xps_recognize,
+ (fz_document_open_fn *)&xps_open_document,
+ (fz_document_open_with_stream_fn *)&xps_open_document_with_stream
+};