diff options
author | Robin Watts <robin.watts@artifex.com> | 2014-01-03 16:50:41 +0000 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2014-01-07 10:25:42 +0000 |
commit | 7f009acebb75ff88c1ee934b03fa2d15f7785b32 (patch) | |
tree | 7be547523d730d104c62e4b5d43685dd8bb5bd40 /source | |
parent | 016adfa063293281a0896c62bf22e406b09ddf21 (diff) | |
download | mupdf-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).
Diffstat (limited to 'source')
-rw-r--r-- | source/cbz/mucbz.c | 23 | ||||
-rw-r--r-- | source/fitz/context.c | 4 | ||||
-rw-r--r-- | source/fitz/document-all.c | 9 | ||||
-rw-r--r-- | source/fitz/document-no-run.c | 9 | ||||
-rw-r--r-- | source/fitz/document.c | 163 | ||||
-rw-r--r-- | source/img/muimage.c | 31 | ||||
-rw-r--r-- | source/pdf/pdf-xref-aux.c | 7 | ||||
-rw-r--r-- | source/pdf/pdf-xref.c | 24 | ||||
-rw-r--r-- | source/tools/mudraw.c | 2 | ||||
-rw-r--r-- | source/xps/xps-doc.c | 25 |
10 files changed, 240 insertions, 57 deletions
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 +}; |