diff --git a/.gitmodules b/.gitmodules index ed3ca68e3..8e671c6ed 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,42 +1,42 @@ [submodule "thirdparty/jbig2dec"] path = thirdparty/jbig2dec - url = ../jbig2dec.git + url = http://git.ghostscript.com/jbig2dec.git [submodule "thirdparty/mujs"] path = thirdparty/mujs - url = ../mujs.git + url = http://git.ghostscript.com/mujs.git [submodule "thirdparty/freetype"] path = thirdparty/freetype - url = ../thirdparty-freetype2.git + url = http://git.ghostscript.com/thirdparty-freetype2.git [submodule "thirdparty/gumbo-parser"] path = thirdparty/gumbo-parser - url = ../thirdparty-gumbo-parser.git + url = http://git.ghostscript.com/thirdparty-gumbo-parser.git [submodule "thirdparty/harfbuzz"] path = thirdparty/harfbuzz - url = ../thirdparty-harfbuzz.git + url = http://git.ghostscript.com/thirdparty-harfbuzz.git [submodule "thirdparty/jpeg"] path = thirdparty/libjpeg - url = ../thirdparty-libjpeg.git + url = http://git.ghostscript.com/thirdparty-libjpeg.git [submodule "thirdparty/lcms2"] path = thirdparty/lcms2 - url = ../thirdparty-lcms2.git + url = http://git.ghostscript.com/thirdparty-lcms2.git [submodule "thirdparty/openjpeg"] path = thirdparty/openjpeg - url = ../thirdparty-openjpeg.git + url = http://git.ghostscript.com/thirdparty-openjpeg.git [submodule "thirdparty/zlib"] path = thirdparty/zlib - url = ../thirdparty-zlib.git + url = http://git.ghostscript.com/thirdparty-zlib.git [submodule "thirdparty/curl"] path = thirdparty/curl - url = ../thirdparty-curl.git + url = http://git.ghostscript.com/thirdparty-curl.git [submodule "thirdparty/freeglut"] path = thirdparty/freeglut - url = ../thirdparty-freeglut.git + url = http://git.ghostscript.com/thirdparty-freeglut.git [submodule "thirdparty/tesseract"] path = thirdparty/tesseract - url = ../thirdparty-tesseract.git + url = http://git.ghostscript.com/thirdparty-tesseract.git [submodule "thirdparty/leptonica"] path = thirdparty/leptonica - url = ../thirdparty-leptonica.git + url = http://git.ghostscript.com/thirdparty-leptonica.git [submodule "thirdparty/extract"] path = thirdparty/extract - url = ../extract.git + url = http://git.ghostscript.com/extract.git diff --git a/CHANGES b/CHANGES index 282449608..2893d2994 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,50 @@ +List of changes in MuPDF 1.19.0 + + Removed support for Luratech JBIG2 and JPEG2000 decoders. + + Added 'extract' library for more output options: + Added DOCX output format + Added ODT output format + + Notable new features: + Journal for undo and redo + Snapshot for auto-save and restore (for backgrounding mobile apps) + Reflow document wrapper + Rollover appearance for annotations and widgets + Customize appearance of signed digital signatures + Progress and cancel callbacks to OCR functions + Create signature form fields + + Minor new features: + Support CJK fonts in pdfwrite output + Support JBIG2 images in pdfwrite output + Support opacity for all markup annotation types + High-DPI aware UI in mupdf-gl + mutool extract -a option to embed SMasks as alpha channel + + API changes: + Removed pdf_widget type alias (was always same as pdf_annot) + Updated annotation 'dirty' logic + Fix typo in function and type names: designated name -> distinguished name + More functions available to 'mutool run' + More functions available to Java library + + New unicode scripts and fonts for EPUB: + Dogra, Elymaic, Gondi, Hanifi Rohingya, Masaram Gondi, + Medefaidrin, Nushu, Nyiakeng Puachue Hmong, Old Sogdian, + Sogdian, Soyombo, Wancho, Yezidi, and Zanabazar Square. + + C++ and Python bindings: + C++ and Python bindings now work on Windows. + Python bindings are available as pre-built binaries on pypi.org. + Added demo PDF viewer using the Python MuPDF bindings and PyQt. + + Better access to data in generated wrapper classes. + Improved handling of out-parameters in generated Python. + Text representation of POD types via C++ operator<< and Python str(). + Fixed ref-counting bug in iterators. + Updates for new MuPDF functions. + List of changes in MuPDF 1.18.0 mutool draw: bbox output format. diff --git a/Makerules b/Makerules index 0dc532d22..0fdaecb17 100644 --- a/Makerules +++ b/Makerules @@ -145,6 +145,16 @@ else ifeq ($(OS),MACOS) LD = xcrun ld RANLIB = xcrun ranlib + ifeq (, $(shell which pkg-config)) + $(warning "No pkg-config found, install it for proper integration of libcrypto") + else + HAVE_LIBCRYPTO := $(shell pkg-config --exists 'libcrypto >= 1.1.0' && echo yes) + ifeq ($(HAVE_LIBCRYPTO),yes) + LIBCRYPTO_CFLAGS := $(shell pkg-config --cflags libcrypto) -DHAVE_LIBCRYPTO + LIBCRYPTO_LIBS := $(shell pkg-config --libs libcrypto) + endif + endif + else ifeq ($(OS),Linux) HAVE_OBJCOPY := yes diff --git a/Makethird b/Makethird index b782463cf..cbf12486b 100644 --- a/Makethird +++ b/Makethird @@ -244,18 +244,27 @@ THIRD_SRC += $(EXTRACT_SRC) $(OUT)/thirdparty/extract/%.o: thirdparty/extract/%.c $(CC_CMD) $(WARNING_CFLAGS) $(LIB_CFLAGS) $(EXTRACT_CFLAGS) $(ZLIB_CFLAGS) $(EXTRACT_BUILD_CFLAGS) +# The first python3 command in the next two rules returns 0 (success) iff +# python3 exists and is version 3.6 or later. + thirdparty/extract/src/docx_template.c: thirdparty/extract/src/template.docx thirdparty/extract/src/docx_template_build.py - $(QUIET_GEN) python3 thirdparty/extract/src/docx_template_build.py \ - -i thirdparty/extract/src/template.docx \ - -n docx \ - -o thirdparty/extract/src/docx_template + $(QUIET_GEN) if python3 -c 'import sys; sys.exit(sys.version_info < (3,6))'; \ + then python3 thirdparty/extract/src/docx_template_build.py \ + -i thirdparty/extract/src/template.docx \ + -n docx \ + -o thirdparty/extract/src/docx_template ; \ + else echo python3 is older than 3.6 so not running docx_template_build.py; \ + fi @touch $@ thirdparty/extract/src/odt_template.c: thirdparty/extract/src/template.odt thirdparty/extract/src/docx_template_build.py - $(QUIET_GEN) python3 thirdparty/extract/src/docx_template_build.py \ - -i thirdparty/extract/src/template.odt \ - -n odt \ - -o thirdparty/extract/src/odt_template + $(QUIET_GEN) if python3 -c 'import sys; sys.exit(sys.version_info < (3,6))'; \ + then python3 thirdparty/extract/src/docx_template_build.py \ + -i thirdparty/extract/src/template.odt \ + -n odt \ + -o thirdparty/extract/src/odt_template ; \ + else echo python3 is older than 3.6 so not running docx_template_build.py; \ + fi @touch $@ generate: thirdparty/extract/src/docx_template.c diff --git a/include/mupdf/fitz/pixmap.h b/include/mupdf/fitz/pixmap.h index 8a139240f..856563900 100644 --- a/include/mupdf/fitz/pixmap.h +++ b/include/mupdf/fitz/pixmap.h @@ -294,6 +294,11 @@ void fz_clear_pixmap(fz_context *ctx, fz_pixmap *pix); */ void fz_invert_pixmap(fz_context *ctx, fz_pixmap *pix); +/** + Invert the alpha fo all the pixels in a pixmap. +*/ +void fz_invert_pixmap_alpha(fz_context *ctx, fz_pixmap *pix); + /** Transform the pixels in a pixmap so that luminance of each pixel is inverted, and the chrominance remains unchanged (as diff --git a/include/mupdf/fitz/version.h b/include/mupdf/fitz/version.h index 1b5c3e0e0..2d3f6b81d 100644 --- a/include/mupdf/fitz/version.h +++ b/include/mupdf/fitz/version.h @@ -23,9 +23,9 @@ #ifndef MUPDF_FITZ_VERSION_H #define MUPDF_FITZ_VERSION_H #ifndef FZ_VERSION -#define FZ_VERSION "1.18.0" +#define FZ_VERSION "1.19.0" #define FZ_VERSION_MAJOR 1 -#define FZ_VERSION_MINOR 18 +#define FZ_VERSION_MINOR 19 #define FZ_VERSION_PATCH 0 #endif #endif diff --git a/scripts/pypackage.py b/scripts/pypackage.py index 505ed44bb..e006ed1a6 100755 --- a/scripts/pypackage.py +++ b/scripts/pypackage.py @@ -497,7 +497,26 @@ def make_windows( prefix = item[:s+1] for item in items: assert item.startswith(prefix) - t.extractall() + def is_within_directory(directory, target): + + abs_directory = os.path.abspath(directory) + abs_target = os.path.abspath(target) + + prefix = os.path.commonprefix([abs_directory, abs_target]) + + return prefix == abs_directory + + def safe_extract(tar, path=".", members=None, *, numeric_owner=False): + + for member in tar.getmembers(): + member_path = os.path.join(path, member.name) + if not is_within_directory(path, member_path): + raise Exception("Attempted Path Traversal in Tar File") + + tar.extractall(path, members, numeric_owner=numeric_owner) + + + safe_extract(t) directory = prefix os.makedirs(out_dir, exist_ok=True) diff --git a/source/fitz/pixmap.c b/source/fitz/pixmap.c index b71ecfa81..496b975b0 100644 --- a/source/fitz/pixmap.c +++ b/source/fitz/pixmap.c @@ -964,6 +964,29 @@ fz_invert_pixmap(fz_context *ctx, fz_pixmap *pix) } } +void +fz_invert_pixmap_alpha(fz_context *ctx, fz_pixmap *pix) +{ + unsigned char *s = pix->samples; + int x, y; + int n1 = pix->n - pix->alpha; + int n = pix->n; + + if (!pix->alpha) + return; + + for (y = 0; y < pix->h; y++) + { + s += n1; + for (x = 0; x < pix->w; x++) + { + *s = 255 - *s; + s += n; + } + s += pix->stride - pix->w * n; + } +} + void fz_invert_pixmap_rect(fz_context *ctx, fz_pixmap *image, fz_irect rect) { unsigned char *p; diff --git a/source/pdf/pdf-annot.c b/source/pdf/pdf-annot.c index a3ec33171..c9006425a 100644 --- a/source/pdf/pdf-annot.c +++ b/source/pdf/pdf-annot.c @@ -2735,7 +2735,9 @@ int pdf_set_annot_field_value(fz_context *ctx, pdf_document *doc, pdf_annot *ann void pdf_set_annot_appearance(fz_context *ctx, pdf_annot *annot, const char *appearance, const char *state, fz_matrix ctm, fz_rect bbox, pdf_obj *res, fz_buffer *contents) { - pdf_obj *form, *ap, *app; + pdf_obj *form = NULL; + pdf_obj *ap, *app; + pdf_obj *app_name = NULL; begin_annot_op(ctx, annot, "Set appearance stream"); @@ -2743,30 +2745,41 @@ pdf_set_annot_appearance(fz_context *ctx, pdf_annot *annot, const char *appearan appearance = "N"; fz_var(form); + fz_var(app_name); fz_try(ctx) { - form = pdf_new_xobject(ctx, annot->page->doc, bbox, ctm, res, contents); - form = pdf_add_object_drop(ctx, annot->page->doc, form); - ap = pdf_dict_get(ctx, annot->obj, PDF_NAME(AP)); if (!ap) ap = pdf_dict_put_dict(ctx, annot->obj, PDF_NAME(AP), 1); if (!state) - pdf_dict_puts(ctx, ap, appearance, form); + form = pdf_keep_obj(ctx, pdf_dict_gets(ctx, ap, appearance)); else { if (strcmp(appearance, "N") && strcmp(appearance, "R") && strcmp(appearance, "D")) fz_throw(ctx, FZ_ERROR_GENERIC, "Unknown annotation appearance"); - app = pdf_dict_put_dict(ctx, ap, pdf_new_name(ctx, appearance), 2); - pdf_dict_puts(ctx, app, state, form); + app_name = pdf_new_name(ctx, appearance); + app = pdf_dict_get(ctx, ap, app_name); + if (!app) + app = pdf_dict_put_dict(ctx, ap, app_name, 2); + form = pdf_keep_obj(ctx, pdf_dict_gets(ctx, ap, appearance)); } + if (!form) + form = pdf_new_xobject(ctx, annot->page->doc, bbox, ctm, res, contents); + else + pdf_update_xobject(ctx, annot->page->doc, form, bbox, ctm, res, contents); + + if (!state) + pdf_dict_puts(ctx, ap, appearance, form); + else + pdf_dict_puts(ctx, app, state, form); } fz_always(ctx) { pdf_drop_obj(ctx, form); + pdf_drop_obj(ctx, app_name); end_annot_op(ctx, annot); } fz_catch(ctx) diff --git a/source/pdf/pdf-clean.c b/source/pdf/pdf-clean.c index e54024d64..e1071e923 100644 --- a/source/pdf/pdf-clean.c +++ b/source/pdf/pdf-clean.c @@ -527,8 +527,14 @@ pdf_redact_image_imp(fz_context *ctx, fz_matrix ctm, fz_image *image, fz_pixmap if (!pixmap) { fz_pixmap *original = fz_get_pixmap_from_image(ctx, image, NULL, NULL, NULL, NULL); + int imagemask = image->imagemask; + fz_try(ctx) + { pixmap = fz_clone_pixmap(ctx, original); + if (imagemask) + fz_invert_pixmap_alpha(ctx, pixmap); + } fz_always(ctx) fz_drop_pixmap(ctx, original); fz_catch(ctx) @@ -684,8 +690,13 @@ pdf_redact_image_filter_pixels(fz_context *ctx, void *opaque, fz_matrix ctm, con if (redacted) { + int imagemask = image->imagemask; + fz_try(ctx) + { image = fz_new_image_from_pixmap(ctx, redacted, NULL); + image->imagemask = imagemask; + } fz_always(ctx) fz_drop_pixmap(ctx, redacted); fz_catch(ctx) diff --git a/source/pdf/pdf-font-add.c b/source/pdf/pdf-font-add.c index ddba13f10..f684c3d2d 100644 --- a/source/pdf/pdf-font-add.c +++ b/source/pdf/pdf-font-add.c @@ -108,7 +108,7 @@ pdf_add_font_file(fz_context *ctx, pdf_document *doc, fz_font *font) if (FT_Get_Sfnt_Table(font->ft_face, FT_SFNT_HEAD)) pdf_dict_put(ctx, obj, PDF_NAME(Subtype), PDF_NAME(OpenType)); else - pdf_dict_put(ctx, obj, PDF_NAME(Subtype), PDF_NAME(Type1C)); + pdf_dict_put(ctx, obj, PDF_NAME(Subtype), PDF_NAME(CIDFontType0C)); break; } ref = pdf_add_object(ctx, doc, obj); diff --git a/thirdparty/tesseract b/thirdparty/tesseract index 1df5db947..a25ae8dc4 160000 --- a/thirdparty/tesseract +++ b/thirdparty/tesseract @@ -1 +1 @@ -Subproject commit 1df5db947b3ce356cfb9a80bed4e8cdd4cc340bc +Subproject commit a25ae8dc4cc97b191bf5ea11365a05a78c566698