summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile23
-rw-r--r--android/jni/Core.mk3
-rw-r--r--android/src/com/artifex/mupdf/MuPDFActivity.java5
-rw-r--r--android/src/com/artifex/mupdf/PageView.java35
-rw-r--r--android/src/com/artifex/mupdf/ReaderView.java5
-rw-r--r--apps/man/mubusy.177
-rw-r--r--apps/man/mudraw.11
-rw-r--r--apps/man/mupdf.13
-rw-r--r--apps/man/mupdfclean.139
-rw-r--r--apps/man/mupdfshow.142
-rw-r--r--apps/mubusy.c93
-rw-r--r--apps/mubusy_draw.c2
-rw-r--r--apps/mubusy_pdfclean.c2
-rw-r--r--apps/mubusy_pdfextract.c2
-rw-r--r--apps/mubusy_pdfinfo.c2
-rw-r--r--apps/mubusy_pdfshow.c2
-rw-r--r--apps/mudraw.c42
-rw-r--r--apps/mupdfclean.c679
-rw-r--r--apps/mupdfextract.c9
-rw-r--r--apps/mupdfinfo.c53
-rw-r--r--apps/mupdfposter.c184
-rw-r--r--apps/mupdfshow.c10
-rw-r--r--apps/pdfapp.c34
-rw-r--r--apps/x11_main.c39
-rw-r--r--draw/draw_affine.c16
-rw-r--r--draw/draw_simple_scale.c15
-rw-r--r--fitz/doc_document.c7
-rw-r--r--fitz/filt_basic.c108
-rw-r--r--fitz/filt_faxd.c8
-rw-r--r--fitz/fitz-internal.h12
-rw-r--r--fitz/fitz.h68
-rw-r--r--fitz/res_font.c8
-rw-r--r--fitz/stm_buffer.c15
-rw-r--r--fitz/stm_open.c15
-rw-r--r--ios/Info.plist83
-rw-r--r--ios/main.m46
-rw-r--r--pdf/mupdf-internal.h24
-rw-r--r--pdf/mupdf.h42
-rw-r--r--pdf/pdf_cmap.c2
-rw-r--r--pdf/pdf_font.c2
-rw-r--r--pdf/pdf_form.c22
-rw-r--r--pdf/pdf_image.c13
-rw-r--r--pdf/pdf_interpret.c91
-rw-r--r--pdf/pdf_js_none.c4
-rw-r--r--pdf/pdf_object.c (renamed from pdf/base_object.c)9
-rw-r--r--pdf/pdf_page.c72
-rw-r--r--pdf/pdf_parse.c8
-rw-r--r--pdf/pdf_pattern.c6
-rw-r--r--pdf/pdf_repair.c15
-rw-r--r--pdf/pdf_stream.c126
-rw-r--r--pdf/pdf_type3.c5
-rw-r--r--pdf/pdf_write.c690
-rw-r--r--pdf/pdf_xobject.c18
-rw-r--r--pdf/pdf_xref.c329
-rw-r--r--pdf/pdf_xref_aux.c31
-rw-r--r--scripts/cmapdump.c1
-rw-r--r--scripts/runtohtml.sh18
-rw-r--r--scripts/tohtml.py66
-rw-r--r--win32/libmupdf-v8.vcproj12
-rw-r--r--win32/libmupdf.vcproj16
-rw-r--r--win32/mubusy.vcproj10
-rw-r--r--win32/mupdf.sln55
-rw-r--r--win32/mupdfclean.vcproj246
-rw-r--r--win32/mupdfextract.vcproj246
-rw-r--r--win32/mupdfinfo.vcproj246
-rw-r--r--win32/mupdfshow.vcproj246
-rw-r--r--xps/xps_zip.c30
68 files changed, 2151 insertions, 2338 deletions
diff --git a/.gitignore b/.gitignore
index e86f8687..f1464ca2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,3 +15,4 @@ android/bin
android/libs
android/gen
android/local.properties
+doc/source
diff --git a/Makefile b/Makefile
index 0d10e357..d2045d1c 100644
--- a/Makefile
+++ b/Makefile
@@ -133,19 +133,16 @@ $(OUT)/cmapdump.o : pdf/pdf_cmap.c pdf/pdf_cmap_parse.c
# --- Tools and Apps ---
-MU_APPS := $(addprefix $(OUT)/, mudraw mupdfclean mupdfextract mupdfinfo mupdfshow)
+MUDRAW := $(addprefix $(OUT)/, mudraw)
+$(MUDRAW) : $(FITZ_LIB) $(THIRD_LIBS)
-$(MU_APPS) : $(FITZ_LIB) $(THIRD_LIBS)
-
-BUSY_SRC := $(notdir $(wildcard apps/mubusy_*.c))
-BUSY_APP := $(addprefix $(OUT)/, mubusy)
-$(BUSY_APP) : $(addprefix $(OUT)/, $(BUSY_SRC:%.c=%.o))
-$(BUSY_APP) : $(FITZ_LIB) $(THIRD_LIBS)
+MUBUSY := $(addprefix $(OUT)/, mubusy)
+$(MUBUSY) : $(addprefix $(OUT)/, mupdfclean.o mupdfextract.o mupdfinfo.o mupdfposter.o mupdfshow.o) $(FITZ_LIB) $(THIRD_LIBS)
ifeq "$(NOX11)" ""
-MUPDF := $(OUT)/mupdf
-$(MUPDF) : $(FITZ_LIB) $(THIRD_LIBS)
-$(MUPDF) : $(addprefix $(OUT)/, x11_main.o x11_image.o pdfapp.o)
+MUVIEW := $(OUT)/mupdf
+$(MUVIEW) : $(FITZ_LIB) $(THIRD_LIBS)
+$(MUVIEW) : $(addprefix $(OUT)/, x11_main.o x11_image.o pdfapp.o)
$(LINK_CMD) $(X11_LIBS)
endif
@@ -167,16 +164,16 @@ libdir ?= $(prefix)/lib
incdir ?= $(prefix)/include
mandir ?= $(prefix)/share/man
-install: $(FITZ_LIB) $(MU_APPS) $(MUPDF)
+install: $(FITZ_LIB) $(MUVIEW) $(MUDRAW) $(MUBUSY)
install -d $(bindir) $(libdir) $(incdir) $(mandir)/man1
install $(FITZ_LIB) $(libdir)
install fitz/memento.h fitz/fitz.h pdf/mupdf.h xps/muxps.h cbz/mucbz.h $(incdir)
- install $(MU_APPS) $(MUPDF) $(bindir)
+ install $(MUVIEW) $(MUDRAW) $(MUBUSY) $(bindir)
install $(wildcard apps/man/*.1) $(mandir)/man1
# --- Clean and Default ---
-all: $(THIRD_LIBS) $(FITZ_LIB) $(MU_APPS) $(MUPDF) $(BUSY_APP)
+all: $(THIRD_LIBS) $(FITZ_LIB) $(MUVIEW) $(MUDRAW) $(MUBUSY)
clean:
rm -rf $(OUT)
diff --git a/android/jni/Core.mk b/android/jni/Core.mk
index dbe0e39d..cea16e74 100644
--- a/android/jni/Core.mk
+++ b/android/jni/Core.mk
@@ -73,7 +73,6 @@ LOCAL_SRC_FILES := \
$(MY_ROOT)/draw/draw_path.c \
$(MY_ROOT)/draw/draw_simple_scale.c \
$(MY_ROOT)/draw/draw_unpack.c \
- $(MY_ROOT)/pdf/base_object.c \
$(MY_ROOT)/pdf/pdf_annot.c \
$(MY_ROOT)/pdf/pdf_cmap.c \
$(MY_ROOT)/pdf/pdf_cmap_load.c \
@@ -90,6 +89,7 @@ LOCAL_SRC_FILES := \
$(MY_ROOT)/pdf/pdf_lex.c \
$(MY_ROOT)/pdf/pdf_metrics.c \
$(MY_ROOT)/pdf/pdf_nametree.c \
+ $(MY_ROOT)/pdf/pdf_object.c \
$(MY_ROOT)/pdf/pdf_outline.c \
$(MY_ROOT)/pdf/pdf_page.c \
$(MY_ROOT)/pdf/pdf_parse.c \
@@ -102,6 +102,7 @@ LOCAL_SRC_FILES := \
$(MY_ROOT)/pdf/pdf_unicode.c \
$(MY_ROOT)/pdf/pdf_xobject.c \
$(MY_ROOT)/pdf/pdf_xref.c \
+ $(MY_ROOT)/pdf/pdf_xref_aux.c \
$(MY_ROOT)/xps/xps_common.c \
$(MY_ROOT)/xps/xps_doc.c \
$(MY_ROOT)/xps/xps_glyphs.c \
diff --git a/android/src/com/artifex/mupdf/MuPDFActivity.java b/android/src/com/artifex/mupdf/MuPDFActivity.java
index bdc1971f..5696ea0b 100644
--- a/android/src/com/artifex/mupdf/MuPDFActivity.java
+++ b/android/src/com/artifex/mupdf/MuPDFActivity.java
@@ -289,6 +289,11 @@ public class MuPDFActivity extends Activity
// no longer appropriate, tell the page to remove HQ
((PageView)v).removeHq();
}
+
+ @Override
+ protected void onNotInUse(View v) {
+ ((PageView)v).releaseResources();
+ }
};
mDocView.setAdapter(new MuPDFPageAdapter(this, core));
diff --git a/android/src/com/artifex/mupdf/PageView.java b/android/src/com/artifex/mupdf/PageView.java
index 123d5037..7a0fcfa9 100644
--- a/android/src/com/artifex/mupdf/PageView.java
+++ b/android/src/com/artifex/mupdf/PageView.java
@@ -81,6 +81,36 @@ public abstract class PageView extends ViewGroup {
protected abstract void drawPage(Bitmap bm, int sizeX, int sizeY, int patchX, int patchY, int patchWidth, int patchHeight);
protected abstract LinkInfo[] getLinkInfo();
+ public void releaseResources() {
+ // Cancel pending render task
+ if (mDrawEntire != null) {
+ mDrawEntire.cancel(true);
+ mDrawEntire = null;
+ }
+
+ if (mDrawPatch != null) {
+ mDrawPatch.cancel(true);
+ mDrawPatch = null;
+ }
+
+ mIsBlank = true;
+ mPageNumber = 0;
+
+ if (mSize == null)
+ mSize = mParentSize;
+
+ if (mEntire != null)
+ mEntire.setImageBitmap(null);
+
+ if (mPatch != null)
+ mPatch.setImageBitmap(null);
+
+ if (mBusyIndicator != null) {
+ removeView(mBusyIndicator);
+ mBusyIndicator = null;
+ }
+ }
+
public void blank(int page) {
// Cancel pending render task
if (mDrawEntire != null) {
@@ -88,6 +118,11 @@ public abstract class PageView extends ViewGroup {
mDrawEntire = null;
}
+ if (mDrawPatch != null) {
+ mDrawPatch.cancel(true);
+ mDrawPatch = null;
+ }
+
mIsBlank = true;
mPageNumber = page;
diff --git a/android/src/com/artifex/mupdf/ReaderView.java b/android/src/com/artifex/mupdf/ReaderView.java
index 76bf0eee..fc031471 100644
--- a/android/src/com/artifex/mupdf/ReaderView.java
+++ b/android/src/com/artifex/mupdf/ReaderView.java
@@ -115,6 +115,8 @@ public class ReaderView extends AdapterView<Adapter>
protected void onUnsettle(View v) {};
+ protected void onNotInUse(View v) {};
+
public View getDisplayedView() {
return mChildViews.get(mCurrent);
}
@@ -342,6 +344,7 @@ public class ReaderView extends AdapterView<Adapter>
int ai = childIndices[i];
if (ai < mCurrent - 1 || ai > mCurrent + 1) {
View v = mChildViews.get(ai);
+ onNotInUse(v);
mViewCache.add(v);
removeViewInLayout(v);
mChildViews.remove(ai);
@@ -355,7 +358,7 @@ public class ReaderView extends AdapterView<Adapter>
int numChildren = mChildViews.size();
for (int i = 0; i < numChildren; i++) {
View v = mChildViews.valueAt(i);
- postUnsettle(v);
+ onNotInUse(v);
mViewCache.add(v);
removeViewInLayout(v);
}
diff --git a/apps/man/mubusy.1 b/apps/man/mubusy.1
new file mode 100644
index 00000000..435dba4d
--- /dev/null
+++ b/apps/man/mubusy.1
@@ -0,0 +1,77 @@
+.TH "MUBUSY" "1" "May 10, 2012"
+.\" Please adjust this date whenever revising the manpage.
+.\" no hyphenation
+.nh
+.\" adjust left
+.ad l
+.SH NAME
+mubusy \- all purpose tool for dealing with PDF files
+.SH SYNOPSIS
+mubusy <sub-command> [options]
+.SH DESCRIPTION
+mubusy is a tool based on MuPDF for dealing with PDF files in various manners.
+There are several sub commands available, as described below.
+.SH CLEAN
+mubusy clean [options] input.pdf [output.pdf] [pages]
+.PP
+The clean command pretty prints and rewrites the syntax of a PDF file.
+It can be used to repair broken files, expand compressed streams, filter
+out a range of pages, etc.
+.PP
+If no output file is specified, it will write the cleaned PDF to "out.pdf"
+in the current directory.
+.TP
+.B \-p password
+Use the specified password if the file is encrypted.
+.TP
+.B \-g
+Garbage collect objects that have no references from other objects.
+Give the option twice to renumber all objects and compact the cross reference table.
+Give it three times to merge and reuse duplicate objects.
+.TP
+.B \-d
+Decompress streams. This will make the output file larger, but provides
+easy access for reading and editing the contents with a text editor.
+.TP
+.B pages
+Comma separated list of page ranges to include.
+.SH EXTRACT
+TODO
+.SH INFO
+TODO
+.SH POSTER
+TODO
+.SH SHOW
+mubusy show [options] file.pdf [object numbers ...]
+.PP
+The show command will print the specified objects and streams to stdout.
+Streams are decoded and non-printable characters are represented
+with a period by default.
+.TP
+.B \-b
+Print streams as binary data and omit the object header.
+.TP
+.B \-e
+Print streams in their original encoded (or compressed) form.
+.TP
+.B \-p password
+Use the specified password if the file is encrypted.
+.PP
+Specify objects by number, or use one of the following special names:
+.TP
+.B 'xref' or 'x'
+Print the cross reference table.
+.TP
+.B 'trailer' or 't'
+Print the trailer dictionary.
+.TP
+.B 'pages' or 'p'
+List the object numbers for every page.
+.TP
+.B 'grep' or 'g'
+Print all the objects in the file in a compact one-line format suitable for piping to grep.
+.SH SEE ALSO
+.BR mupdf (1),
+.BR mudraw (1).
+.SH AUTHOR
+MuPDF is Copyright 2006-2012 Artifex Software, Inc.
diff --git a/apps/man/mudraw.1 b/apps/man/mudraw.1
index 41bee152..cbe1b613 100644
--- a/apps/man/mudraw.1
+++ b/apps/man/mudraw.1
@@ -86,5 +86,4 @@ Comma separated list of ranges to render.
.BR mupdfclean (1).
.BR mupdfshow (1).
.SH AUTHOR
-MuPDF was written by Tor Andersson <tor@ghostscript.com>.
MuPDF is Copyright 2006-2012 Artifex Software, Inc.
diff --git a/apps/man/mupdf.1 b/apps/man/mupdf.1
index fc8e9640..dc2dfca1 100644
--- a/apps/man/mupdf.1
+++ b/apps/man/mupdf.1
@@ -86,7 +86,4 @@ Toggle between normal and inverted color rendering.
.BR mupdfdraw (1),
.BR mupdfshow (1).
.SH AUTHOR
-MuPDF was written by Tor Andersson <tor@ghostscript.com>.
MuPDF is Copyright 2006-2012 Artifex Software, Inc.
-.PP
-This manual page was written by Sebastian Rasmussen <sebras@hotmail.com>.
diff --git a/apps/man/mupdfclean.1 b/apps/man/mupdfclean.1
deleted file mode 100644
index 91e796ac..00000000
--- a/apps/man/mupdfclean.1
+++ /dev/null
@@ -1,39 +0,0 @@
-.TH PDFCLEAN 1 "January 27, 2012"
-.\" Please adjust this date whenever revising the manpage.
-.SH NAME
-mupdfclean \- pretty print, decompress and garbage collect PDF files
-.SH SYNOPSIS
-.B mupdfclean
-.RI [ options ]
-.RI input.pdf
-.RI [ output.pdf ]
-.RI [ pages ]
-.SH DESCRIPTION
-.B mupdfclean
-pretty prints and rewrites the contents of a PDF file.
-If no output file is specified, the new file will be written to "out.pdf" in
-the current directory.
-.PP
-.SH OPTIONS
-.TP
-.B \-p password
-Use the specified password if the file is encrypted.
-.TP
-.B \-g
-Garbage collect objects that have no references from other objects.
-Give the option twice to renumber all objects and compact the cross reference table.
-Give it three times to merge and reuse duplicate objects.
-.TP
-.B \-d
-Decompress streams. This will make the output file larger, but provides
-easy access for reading and editing the contents with a text editor.
-.TP
-.B pages
-Comma separated list of ranges to clean.
-.SH SEE ALSO
-.BR mupdf (1),
-.BR mupdfdraw (1).
-.BR mupdfshow (1).
-.SH AUTHOR
-MuPDF was written by Tor Andersson <tor@ghostscript.com>.
-MuPDF is Copyright 2006-2010 Artifex Software, Inc.
diff --git a/apps/man/mupdfshow.1 b/apps/man/mupdfshow.1
deleted file mode 100644
index 451dac6b..00000000
--- a/apps/man/mupdfshow.1
+++ /dev/null
@@ -1,42 +0,0 @@
-.TH PDFSHOW 1 "January 27, 2012"
-.\" Please adjust this date whenever revising the manpage.
-.SH NAME
-mupdfshow \- show objects and streams that make up a PDF document
-.SH SYNOPSIS
-.B mupdfshow
-.RI [ options ]
-.RI file.pdf
-.RI [ xref ]
-.RI [ trailer ]
-.RI [ pages ]
-.RI [ grep ]
-.RI [ object-number... ]
-.SH DESCRIPTION
-.B mupdfshow
-pretty prints the objects and streams specified on the command line.
-Streams are decoded and non-printable characters are represented
-with a period.
-Specify objects with their number.
-The special names xref, trailer and pages will
-respectively print the cross reference, trailer,
-and the object numbers for all pages.
-The special name grep will print all objects in the file
-in a compact one-line format suitable for piping to grep.
-.PP
-.SH OPTIONS
-.TP
-.B \-b
-Print streams as binary data and omit the object header.
-.TP
-.B \-e
-Print streams in their original encoded form.
-.TP
-.B \-p password
-Use the specified password if the file is encrypted.
-.SH SEE ALSO
-.BR mupdf (1),
-.BR mupdfclean (1).
-.BR mupdfdraw (1).
-.SH AUTHOR
-MuPDF was written by Tor Andersson <tor@ghostscript.com>.
-MuPDF is copyright 2006-2012 Artifex Software, Inc.
diff --git a/apps/mubusy.c b/apps/mubusy.c
index a9df26fa..b520d0ec 100644
--- a/apps/mubusy.c
+++ b/apps/mubusy.c
@@ -1,62 +1,83 @@
/*
- * pdfbusy -- combined exe build
+ * mubusy -- swiss army knife of pdf manipulation tools
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#define nelem(x) (sizeof(x)/sizeof((x)[0]))
+
int pdfclean_main(int argc, char *argv[]);
-int draw_main(int argc, char *argv[]);
int pdfextract_main(int argc, char *argv[]);
int pdfinfo_main(int argc, char *argv[]);
+int pdfposter_main(int argc, char *argv[]);
int pdfshow_main(int argc, char *argv[]);
+static struct {
+ int (*func)(int argc, char *argv[]);
+ char *name;
+ char *desc;
+} tools[] = {
+ { pdfclean_main, "clean", "rewrite pdf file" },
+ { pdfextract_main, "extract", "extract font and image resources" },
+ { pdfinfo_main, "info", "show information about pdf resources" },
+ { pdfposter_main, "poster", "split large page into many tiles" },
+ { pdfshow_main, "show", "show internal pdf objects" },
+};
+
static int
-namematch(const char *end, const char *start, const char *match, int len)
+namematch(const char *end, const char *start, const char *match)
{
+ int len = strlen(match);
return ((end-len >= start) && (strncmp(end-len, match, len) == 0));
}
int main(int argc, char **argv)
{
char *start, *end;
+ char buf[32];
+ int i;
+
if (argc == 0)
{
fprintf(stderr, "No command name found!\n");
- exit(EXIT_FAILURE);
+ return 1;
+ }
+
+ /* Check argv[0] */
+
+ if (argc > 0)
+ {
+ end = start = argv[0];
+ while (*end)
+ end++;
+ if ((end-4 >= start) && (end[-4] == '.') && (end[-3] == 'e') && (end[-2] == 'x') && (end[-1] == 'e'))
+ end = end-4;
+ for (i = 0; i < nelem(tools); i++)
+ {
+ strcpy(buf, "mupdf");
+ strcat(buf, tools[i].name);
+ if (namematch(end, start, buf))
+ return tools[i].func(argc, argv);
+ }
}
- end = start = argv[0];
- while (*end)
- end++;
- if ((end-4 >= start) && (end[-4] == '.') && (end[-3] == 'e') && (end[-2] == 'x') && (end[-1] == 'e'))
- end = end-4;
- if (namematch(end, start, "mupdfdraw", 9) || namematch(end, start, "muxpsdraw", 9) || namematch(end, start, "mudraw", 6))
- return draw_main(argc, argv);
- if (namematch(end, start, "mupdfclean", 10))
- return pdfclean_main(argc, argv);
- if (namematch(end, start, "mupdfextract", 12))
- return pdfextract_main(argc, argv);
- if (namematch(end, start, "mupdfshow", 9))
- return pdfshow_main(argc, argv);
- if (namematch(end, start, "mupdfinfo", 9))
- return pdfinfo_main(argc, argv);
- /* And include old names for backward compatibility */
- if (namematch(end, start, "pdfdraw", 7) || namematch(end, start, "xpsdraw", 7))
- return draw_main(argc, argv);
- if (namematch(end, start, "pdfclean", 8))
- return pdfclean_main(argc, argv);
- if (namematch(end, start, "pdfextract", 10))
- return pdfextract_main(argc, argv);
- if (namematch(end, start, "pdfshow", 7))
- return pdfshow_main(argc, argv);
- if (namematch(end, start, "pdfinfo", 7))
- return pdfinfo_main(argc, argv);
-
- fprintf(stderr, "mubusy: Combined build of mupdf/mudraw tools.\n\n");
- fprintf(stderr, "Invoke as one of the following:\n");
- fprintf(stderr, "\tmupdfclean, mudraw, mupdfextract, mupdfinfo, mupdfshow.\n");
-
- return 0;
+ /* Check argv[1] */
+
+ if (argc > 1)
+ {
+ for (i = 0; i < nelem(tools); i++)
+ if (!strcmp(tools[i].name, argv[1]))
+ return tools[i].func(argc - 1, argv + 1);
+ }
+
+ /* Print usage */
+
+ fprintf(stderr, "usage: mubusy <command> [options]\n");
+
+ for (i = 0; i < nelem(tools); i++)
+ fprintf(stderr, "\t%s\t-- %s\n", tools[i].name, tools[i].desc);
+
+ return 1;
}
diff --git a/apps/mubusy_draw.c b/apps/mubusy_draw.c
deleted file mode 100644
index 26b9bd6d..00000000
--- a/apps/mubusy_draw.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define MUPDF_COMBINED_EXE
-#include "mudraw.c"
diff --git a/apps/mubusy_pdfclean.c b/apps/mubusy_pdfclean.c
deleted file mode 100644
index bc3456d1..00000000
--- a/apps/mubusy_pdfclean.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define MUPDF_COMBINED_EXE
-#include "mupdfclean.c"
diff --git a/apps/mubusy_pdfextract.c b/apps/mubusy_pdfextract.c
deleted file mode 100644
index 30f661a3..00000000
--- a/apps/mubusy_pdfextract.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define MUPDF_COMBINED_EXE
-#include "mupdfextract.c"
diff --git a/apps/mubusy_pdfinfo.c b/apps/mubusy_pdfinfo.c
deleted file mode 100644
index df947543..00000000
--- a/apps/mubusy_pdfinfo.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define MUPDF_COMBINED_EXE
-#include "mupdfinfo.c"
diff --git a/apps/mubusy_pdfshow.c b/apps/mubusy_pdfshow.c
deleted file mode 100644
index 320b93aa..00000000
--- a/apps/mubusy_pdfshow.c
+++ /dev/null
@@ -1,2 +0,0 @@
-#define MUPDF_COMBINED_EXE
-#include "mupdfshow.c"
diff --git a/apps/mudraw.c b/apps/mudraw.c
index 8abce8ed..6a90398f 100644
--- a/apps/mudraw.c
+++ b/apps/mudraw.c
@@ -34,11 +34,14 @@ static int fit = 0;
static fz_text_sheet *sheet = NULL;
static fz_colorspace *colorspace;
static char *filename;
+static int files = 0;
static struct {
int count, total;
int min, max;
int minpage, maxpage;
+ char *minfilename;
+ char *maxfilename;
} timing;
static void usage(void)
@@ -348,11 +351,12 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum)
{
timing.min = diff;
timing.minpage = pagenum;
+ timing.minfilename = filename;
}
if (diff > timing.max)
{
timing.max = diff;
- timing.maxpage = pagenum;
+ timing.maxfilename = filename;
}
timing.total += diff;
timing.count ++;
@@ -368,17 +372,17 @@ static void drawpage(fz_context *ctx, fz_document *doc, int pagenum)
static void drawrange(fz_context *ctx, fz_document *doc, char *range)
{
- int page, spage, epage, final;
+ int page, spage, epage, pagecount;
char *spec, *dash;
- final = fz_count_pages(doc);
+ pagecount = fz_count_pages(doc);
spec = fz_strsep(&range, ",");
while (spec)
{
dash = strchr(spec, '-');
if (dash == spec)
- spage = epage = final;
+ spage = epage = pagecount;
else
spage = epage = atoi(spec);
@@ -387,11 +391,11 @@ static void drawrange(fz_context *ctx, fz_document *doc, char *range)
if (strlen(dash) > 1)
epage = atoi(dash + 1);
else
- epage = final;
+ epage = pagecount;
}
- spage = CLAMP(spage, 1, final);
- epage = CLAMP(epage, 1, final);
+ spage = CLAMP(spage, 1, pagecount);
+ epage = CLAMP(epage, 1, pagecount);
if (spage < epage)
for (page = spage; page <= epage; page++)
@@ -488,6 +492,8 @@ int main(int argc, char **argv)
timing.max = 0;
timing.minpage = 0;
timing.maxpage = 0;
+ timing.minfilename = "";
+ timing.maxfilename = "";
if (showxml || showtext == TEXT_XML)
printf("<?xml version=\"1.0\"?>\n");
@@ -511,6 +517,7 @@ int main(int argc, char **argv)
while (fz_optind < argc)
{
filename = argv[fz_optind++];
+ files++;
fz_try(ctx)
{
@@ -549,6 +556,7 @@ int main(int argc, char **argv)
fz_catch(ctx)
{
fz_close_document(doc);
+ fprintf(stderr, "error: cannot draw '%s'\n", filename);
}
if (showtext == TEXT_HTML)
@@ -562,12 +570,22 @@ int main(int argc, char **argv)
if (showtext)
fz_free_text_sheet(ctx, sheet);
- if (showtime)
+ if (showtime && timing.count > 0)
{
- printf("total %dms / %d pages for an average of %dms\n",
- timing.total, timing.count, timing.total / timing.count);
- printf("fastest page %d: %dms\n", timing.minpage, timing.min);
- printf("slowest page %d: %dms\n", timing.maxpage, timing.max);
+ if (files == 1)
+ {
+ printf("total %dms / %d pages for an average of %dms\n",
+ timing.total, timing.count, timing.total / timing.count);
+ printf("fastest page %d: %dms\n", timing.minpage, timing.min);
+ printf("slowest page %d: %dms\n", timing.maxpage, timing.max);
+ }
+ else
+ {
+ printf("total %dms / %d pages for an average of %dms in %d files\n",
+ timing.total, timing.count, timing.total / timing.count, files);
+ printf("fastest page %d: %dms (%s)\n", timing.minpage, timing.min, timing.minfilename);
+ printf("slowest page %d: %dms (%s)\n", timing.maxpage, timing.max, timing.maxfilename);
+ }
}
fz_free_context(ctx);
diff --git a/apps/mupdfclean.c b/apps/mupdfclean.c
index 5b95fdae..ad210bdb 100644
--- a/apps/mupdfclean.c
+++ b/apps/mupdfclean.c
@@ -12,31 +12,13 @@
#include "fitz.h"
#include "mupdf-internal.h"
-static FILE *out = NULL;
-
-enum
-{
- expand_images = 1,
- expand_fonts = 2,
- expand_all = -1
-};
-
-static char *uselist = NULL;
-static int *ofslist = NULL;
-static int *genlist = NULL;
-static int *renumbermap = NULL;
-
-static int dogarbage = 0;
-static int doexpand = 0;
-static int doascii = 0;
-
static pdf_document *xref = NULL;
static fz_context *ctx = NULL;
static void usage(void)
{
fprintf(stderr,
- "usage: pdfclean [options] input.pdf [output.pdf] [pages]\n"
+ "usage: mubusy clean [options] input.pdf [output.pdf] [pages]\n"
"\t-p -\tpassword\n"
"\t-g\tgarbage collect unused objects\n"
"\t-gg\tin addition to -g compact xref table\n"
@@ -50,251 +32,6 @@ static void usage(void)
}
/*
- * Garbage collect objects not reachable from the trailer.
- */
-
-static pdf_obj *sweepref(pdf_obj *obj)
-{
- int num = pdf_to_num(obj);
- int gen = pdf_to_gen(obj);
-
- if (num < 0 || num >= xref->len)
- return NULL;
- if (uselist[num])
- return NULL;
-
- uselist[num] = 1;
-
- /* Bake in /Length in stream objects */
- fz_try(ctx)
- {
- if (pdf_is_stream(xref, num, gen))
- {
- pdf_obj *len = pdf_dict_gets(obj, "Length");
- if (pdf_is_indirect(len))
- {
- uselist[pdf_to_num(len)] = 0;
- len = pdf_resolve_indirect(len);
- pdf_dict_puts(obj, "Length", len);
- }
- }
- }
- fz_catch(ctx)
- {
- /* Leave broken */
- }
-
- return pdf_resolve_indirect(obj);
-}
-
-static void sweepobj(pdf_obj *obj)
-{
- int i;
-
- if (pdf_is_indirect(obj))
- obj = sweepref(obj);
-
- if (pdf_is_dict(obj))
- {
- int n = pdf_dict_len(obj);
- for (i = 0; i < n; i++)
- sweepobj(pdf_dict_get_val(obj, i));
- }
-
- else if (pdf_is_array(obj))
- {
- int n = pdf_array_len(obj);
- for (i = 0; i < n; i++)
- sweepobj(pdf_array_get(obj, i));
- }
-}
-
-/*
- * Scan for and remove duplicate objects (slow)
- */
-
-static void removeduplicateobjs(void)
-{
- int num, other;
-
- for (num = 1; num < xref->len; num++)
- {
- /* Only compare an object to objects preceding it */
- for (other = 1; other < num; other++)
- {
- pdf_obj *a, *b;
-
- if (num == other || !uselist[num] || !uselist[other])
- continue;
-
- /*
- * Comparing stream objects data contents would take too long.
- *
- * pdf_is_stream calls pdf_cache_object and ensures
- * that the xref table has the objects loaded.
- */
- fz_try(ctx)
- {
- if (pdf_is_stream(xref, num, 0) || pdf_is_stream(xref, other, 0))
- continue;
- }
- fz_catch(ctx)
- {
- /* Assume different */
- }
-
- a = xref->table[num].obj;
- b = xref->table[other].obj;
-
- a = pdf_resolve_indirect(a);
- b = pdf_resolve_indirect(b);
-
- if (pdf_objcmp(a, b))
- continue;
-
- /* Keep the lowest numbered object */
- renumbermap[num] = MIN(num, other);
- renumbermap[other] = MIN(num, other);
- uselist[MAX(num, other)] = 0;
-
- /* One duplicate was found, do not look for another */
- break;
- }
- }
-}
-
-/*
- * Renumber objects sequentially so the xref is more compact
- */
-
-static void compactxref(void)
-{
- int num, newnum;
-
- /*
- * Update renumbermap in-place, clustering all used
- * objects together at low object ids. Objects that
- * already should be renumbered will have their new
- * object ids be updated to reflect the compaction.
- */
-
- newnum = 1;
- for (num = 1; num < xref->len; num++)
- {
- if (uselist[num] && renumbermap[num] == num)
- renumbermap[num] = newnum++;
- else if (renumbermap[num] != num)
- renumbermap[num] = renumbermap[renumbermap[num]];
- }
-}
-
-/*
- * Update indirect objects according to renumbering established when
- * removing duplicate objects and compacting the xref.
- */
-
-static void renumberobj(pdf_obj *obj)
-{
- int i;
- fz_context *ctx = xref->ctx;
-
- if (pdf_is_dict(obj))
- {
- int n = pdf_dict_len(obj);
- for (i = 0; i < n; i++)
- {
- pdf_obj *key = pdf_dict_get_key(obj, i);
- pdf_obj *val = pdf_dict_get_val(obj, i);
- if (pdf_is_indirect(val))
- {
- val = pdf_new_indirect(ctx, renumbermap[pdf_to_num(val)], 0, xref);
- fz_dict_put(obj, key, val);
- pdf_drop_obj(val);
- }
- else
- {
- renumberobj(val);
- }
- }
- }
-
- else if (pdf_is_array(obj))
- {
- int n = pdf_array_len(obj);
- for (i = 0; i < n; i++)
- {
- pdf_obj *val = pdf_array_get(obj, i);
- if (pdf_is_indirect(val))
- {
- val = pdf_new_indirect(ctx, renumbermap[pdf_to_num(val)], 0, xref);
- pdf_array_put(obj, i, val);
- pdf_drop_obj(val);
- }
- else
- {
- renumberobj(val);
- }
- }
- }
-}
-
-static void renumberobjs(void)
-{
- pdf_xref_entry *oldxref;
- int newlen;
- int num;
-
- /* Apply renumber map to indirect references in all objects in xref */
- renumberobj(xref->trailer);
- for (num = 0; num < xref->len; num++)
- {
- pdf_obj *obj = xref->table[num].obj;
-
- if (pdf_is_indirect(obj))
- {
- obj = pdf_new_indirect(ctx, renumbermap[pdf_to_num(obj)], 0, xref);
- pdf_update_object(xref, num, 0, obj);
- pdf_drop_obj(obj);
- }
- else
- {
- renumberobj(obj);
- }
- }
-
- /* Create new table for the reordered, compacted xref */
- oldxref = xref->table;
- xref->table = fz_malloc_array(xref->ctx, xref->len, sizeof(pdf_xref_entry));
- xref->table[0] = oldxref[0];
-
- /* Move used objects into the new compacted xref */
- newlen = 0;
- for (num = 1; num < xref->len; num++)
- {
- if (uselist[num])
- {
- if (newlen < renumbermap[num])
- newlen = renumbermap[num];
- xref->table[renumbermap[num]] = oldxref[num];
- }
- else
- {
- if (oldxref[num].obj)
- pdf_drop_obj(oldxref[num].obj);
- }
- }
-
- fz_free(xref->ctx, oldxref);
-
- /* Update the used objects count in compacted xref */
- xref->len = newlen + 1;
-
- /* Update list of used objects to fit with compacted xref */
- for (num = 1; num < xref->len; num++)
- uselist[num] = 1;
-}
-
-/*
* Recreate page tree to only retain specified pages.
*/
@@ -312,7 +49,7 @@ static void retainpages(int argc, char **argv)
pdf_dict_puts(root, "Type", pdf_dict_gets(oldroot, "Type"));
pdf_dict_puts(root, "Pages", pdf_dict_gets(oldroot, "Pages"));
- pdf_update_object(xref, pdf_to_num(oldroot), pdf_to_gen(oldroot), root);
+ pdf_update_object(xref, pdf_to_num(oldroot), root);
pdf_drop_obj(root);
@@ -323,17 +60,18 @@ static void retainpages(int argc, char **argv)
/* Retain pages specified */
while (argc - fz_optind)
{
- int page, spage, epage;
+ int page, spage, epage, pagecount;
char *spec, *dash;
char *pagelist = argv[fz_optind];
+ pagecount = pdf_count_pages(xref);
spec = fz_strsep(&pagelist, ",");
while (spec)
{
dash = strchr(spec, '-');
if (dash == spec)
- spage = epage = pdf_count_pages(xref);
+ spage = epage = pagecount;
else
spage = epage = atoi(spec);
@@ -342,16 +80,14 @@ static void retainpages(int argc, char **argv)
if (strlen(dash) > 1)
epage = atoi(dash + 1);
else
- epage = pdf_count_pages(xref);
+ epage = pagecount;
}
if (spage > epage)
page = spage, spage = epage, epage = page;
- if (spage < 1)
- spage = 1;
- if (epage > pdf_count_pages(xref))
- epage = pdf_count_pages(xref);
+ spage = CLAMP(spage, 1, pagecount);
+ epage = CLAMP(epage, 1, pagecount);
for (page = spage; page <= epage; page++)
{
@@ -415,352 +151,29 @@ static void retainpages(int argc, char **argv)
}
}
-/*
- * Make sure we have loaded objects from object streams.
- */
-
-static void preloadobjstms(void)
-{
- pdf_obj *obj;
- int num;
-
- for (num = 0; num < xref->len; num++)
- {
- if (xref->table[num].type == 'o')
- {
- obj = pdf_load_object(xref, num, 0);
- pdf_drop_obj(obj);
- }
- }
-}
-
-/*
- * Save streams and objects to the output
- */
-
-static inline int isbinary(int c)
-{
- if (c == '\n' || c == '\r' || c == '\t')
- return 0;
- return c < 32 || c > 127;
-}
-
-static int isbinarystream(fz_buffer *buf)
-{
- int i;
- for (i = 0; i < buf->len; i++)
- if (isbinary(buf->data[i]))
- return 1;
- return 0;
-}
-
-static fz_buffer *hexbuf(unsigned char *p, int n)
-{
- static const char hex[16] = "0123456789abcdef";
- fz_buffer *buf;
- int x = 0;
-
- buf = fz_new_buffer(ctx, n * 2 + (n / 32) + 2);
-
- while (n--)
- {
- buf->data[buf->len++] = hex[*p >> 4];
- buf->data[buf->len++] = hex[*p & 15];
- if (++x == 32)
- {
- buf->data[buf->len++] = '\n';
- x = 0;
- }
- p++;
- }
-
- buf->data[buf->len++] = '>';
- buf->data[buf->len++] = '\n';
-
- return buf;
-}
-
-static void addhexfilter(pdf_obj *dict)
-{
- pdf_obj *f, *dp, *newf, *newdp;
- pdf_obj *ahx, *nullobj;
-
- ahx = fz_new_name(ctx, "ASCIIHexDecode");
- nullobj = pdf_new_null(ctx);
- newf = newdp = NULL;
-
- f = pdf_dict_gets(dict, "Filter");
- dp = pdf_dict_gets(dict, "DecodeParms");
-
- if (pdf_is_name(f))
- {
- newf = pdf_new_array(ctx, 2);
- pdf_array_push(newf, ahx);
- pdf_array_push(newf, f);
- f = newf;
- if (pdf_is_dict(dp))
- {
- newdp = pdf_new_array(ctx, 2);
- pdf_array_push(newdp, nullobj);
- pdf_array_push(newdp, dp);
- dp = newdp;
- }
- }
- else if (pdf_is_array(f))
- {
- pdf_array_insert(f, ahx);
- if (pdf_is_array(dp))
- pdf_array_insert(dp, nullobj);
- }
- else
- f = ahx;
-
- pdf_dict_puts(dict, "Filter", f);
- if (dp)
- pdf_dict_puts(dict, "DecodeParms", dp);
-
- pdf_drop_obj(ahx);
- pdf_drop_obj(nullobj);
- if (newf)
- pdf_drop_obj(newf);
- if (newdp)
- pdf_drop_obj(newdp);
-}
-
-static void copystream(pdf_obj *obj, int num, int gen)
-{
- fz_buffer *buf, *tmp;
- pdf_obj *newlen;
-
- buf = pdf_load_raw_stream(xref, num, gen);
-
- if (doascii && isbinarystream(buf))
- {
- tmp = hexbuf(buf->data, buf->len);
- fz_drop_buffer(ctx, buf);
- buf = tmp;
-
- addhexfilter(obj);
-
- newlen = pdf_new_int(ctx, buf->len);
- pdf_dict_puts(obj, "Length", newlen);
- pdf_drop_obj(newlen);
- }
-
- fprintf(out, "%d %d obj\n", num, gen);
- pdf_fprint_obj(out, obj, doexpand == 0);
- fprintf(out, "stream\n");
- fwrite(buf->data, 1, buf->len, out);
- fprintf(out, "endstream\nendobj\n\n");
-
- fz_drop_buffer(ctx, buf);
-}
-
-static void expandstream(pdf_obj *obj, int num, int gen)
-{
- fz_buffer *buf, *tmp;
- pdf_obj *newlen;
-
- buf = pdf_load_stream(xref, num, gen);
-
- pdf_dict_dels(obj, "Filter");
- pdf_dict_dels(obj, "DecodeParms");
-
- if (doascii && isbinarystream(buf))
- {
- tmp = hexbuf(buf->data, buf->len);
- fz_drop_buffer(ctx, buf);
- buf = tmp;
-
- addhexfilter(obj);
- }
-
- newlen = pdf_new_int(ctx, buf->len);
- pdf_dict_puts(obj, "Length", newlen);
- pdf_drop_obj(newlen);
-
- fprintf(out, "%d %d obj\n", num, gen);
- pdf_fprint_obj(out, obj, doexpand == 0);
- fprintf(out, "stream\n");
- fwrite(buf->data, 1, buf->len, out);
- fprintf(out, "endstream\nendobj\n\n");
-
- fz_drop_buffer(ctx, buf);
-}
-
-static void writeobject(int num, int gen)
-{
- pdf_obj *obj;
- pdf_obj *type;
-
- obj = pdf_load_object(xref, num, gen);
-
- /* skip ObjStm and XRef objects */
- if (pdf_is_dict(obj))
- {
- type = pdf_dict_gets(obj, "Type");
- if (pdf_is_name(type) && !strcmp(pdf_to_name(type), "ObjStm"))
- {
- uselist[num] = 0;
- pdf_drop_obj(obj);
- return;
- }
- if (pdf_is_name(type) && !strcmp(pdf_to_name(type), "XRef"))
- {
- uselist[num] = 0;
- pdf_drop_obj(obj);
- return;
- }
- }
-
- if (!pdf_is_stream(xref, num, gen))
- {
- fprintf(out, "%d %d obj\n", num, gen);
- pdf_fprint_obj(out, obj, doexpand == 0);
- fprintf(out, "endobj\n\n");
- }
- else
- {
- int dontexpand = 0;
- if (doexpand != 0 && doexpand != expand_all)
- {
- pdf_obj *o;
-
- if ((o = pdf_dict_gets(obj, "Type"), !strcmp(pdf_to_name(o), "XObject")) &&
- (o = pdf_dict_gets(obj, "Subtype"), !strcmp(pdf_to_name(o), "Image")))
- dontexpand = !(doexpand & expand_images);
- if (o = pdf_dict_gets(obj, "Type"), !strcmp(pdf_to_name(o), "Font"))
- dontexpand = !(doexpand & expand_fonts);
- if (o = pdf_dict_gets(obj, "Type"), !strcmp(pdf_to_name(o), "FontDescriptor"))
- dontexpand = !(doexpand & expand_fonts);
- if ((o = pdf_dict_gets(obj, "Length1")) != NULL)
- dontexpand = !(doexpand & expand_fonts);
- if ((o = pdf_dict_gets(obj, "Length2")) != NULL)
- dontexpand = !(doexpand & expand_fonts);
- if ((o = pdf_dict_gets(obj, "Length3")) != NULL)
- dontexpand = !(doexpand & expand_fonts);
- if (o = pdf_dict_gets(obj, "Subtype"), !strcmp(pdf_to_name(o), "Type1C"))
- dontexpand = !(doexpand & expand_fonts);
- if (o = pdf_dict_gets(obj, "Subtype"), !strcmp(pdf_to_name(o), "CIDFontType0C"))
- dontexpand = !(doexpand & expand_fonts);
- }
- if (doexpand && !dontexpand && !pdf_is_jpx_image(ctx, obj))
- expandstream(obj, num, gen);
- else
- copystream(obj, num, gen);
- }
-
- pdf_drop_obj(obj);
-}
-
-static void writexref(void)
-{
- pdf_obj *trailer;
- pdf_obj *obj;
- int startxref;
- int num;
-
- startxref = ftell(out);
-
- fprintf(out, "xref\n0 %d\n", xref->len);
- for (num = 0; num < xref->len; num++)
- {
- if (uselist[num])
- fprintf(out, "%010d %05d n \n", ofslist[num], genlist[num]);
- else
- fprintf(out, "%010d %05d f \n", ofslist[num], genlist[num]);
- }
- fprintf(out, "\n");
-
- trailer = pdf_new_dict(ctx, 5);
-
- obj = pdf_new_int(ctx, xref->len);
- pdf_dict_puts(trailer, "Size", obj);
- pdf_drop_obj(obj);
-
- obj = pdf_dict_gets(xref->trailer, "Info");
- if (obj)
- pdf_dict_puts(trailer, "Info", obj);
-
- obj = pdf_dict_gets(xref->trailer, "Root");
- if (obj)
- pdf_dict_puts(trailer, "Root", obj);
-
- obj = pdf_dict_gets(xref->trailer, "ID");
- if (obj)
- pdf_dict_puts(trailer, "ID", obj);
-
- fprintf(out, "trailer\n");
- pdf_fprint_obj(out, trailer, doexpand == 0);
- fprintf(out, "\n");
-
- pdf_drop_obj(trailer);
-
- fprintf(out, "startxref\n%d\n%%%%EOF\n", startxref);
-}
-
-static void writepdf(void)
-{
- int lastfree;
- int num;
-
- for (num = 0; num < xref->len; num++)
- {
- if (xref->table[num].type == 'f')
- genlist[num] = xref->table[num].gen;
- if (xref->table[num].type == 'n')
- genlist[num] = xref->table[num].gen;
- if (xref->table[num].type == 'o')
- genlist[num] = 0;
-
- if (dogarbage && !uselist[num])
- continue;
-
- if (xref->table[num].type == 'n' || xref->table[num].type == 'o')
- {
- uselist[num] = 1;
- ofslist[num] = ftell(out);
- writeobject(num, genlist[num]);
- }
- }
-
- /* Construct linked list of free object slots */
- lastfree = 0;
- for (num = 0; num < xref->len; num++)
- {
- if (!uselist[num])
- {
- genlist[num]++;
- ofslist[lastfree] = num;
- lastfree = num;
- }
- }
-
- writexref();
-}
-
-#ifdef MUPDF_COMBINED_EXE
int pdfclean_main(int argc, char **argv)
-#else
-int main(int argc, char **argv)
-#endif
{
char *infile;
char *outfile = "out.pdf";
char *password = "";
- int c, num;
+ int c;
int subset;
+ fz_write_options opts;
+
+ opts.dogarbage = 0;
+ opts.doexpand = 0;
+ opts.doascii = 0;
while ((c = fz_getopt(argc, argv, "adfgip:")) != -1)
{
switch (c)
{
case 'p': password = fz_optarg; break;
- case 'g': dogarbage ++; break;
- case 'd': doexpand ^= expand_all; break;
- case 'f': doexpand ^= expand_fonts; break;
- case 'i': doexpand ^= expand_images; break;
- case 'a': doascii ++; break;
+ case 'g': opts.dogarbage ++; break;
+ case 'd': opts.doexpand ^= fz_expand_all; break;
+ case 'f': opts.doexpand ^= fz_expand_fonts; break;
+ case 'i': opts.doexpand ^= fz_expand_images; break;
+ case 'a': opts.doascii ++; break;
default: usage(); break;
}
}
@@ -787,66 +200,16 @@ int main(int argc, char **argv)
exit(1);
}
- xref = pdf_open_document(ctx, infile);
+ xref = pdf_open_document_no_run(ctx, infile);
if (pdf_needs_password(xref))
if (!pdf_authenticate_password(xref, password))
fz_throw(ctx, "cannot authenticate password: %s", infile);
- out = fopen(outfile, "wb");
- if (!out)
- fz_throw(ctx, "cannot open output file '%s'", outfile);
-
- fprintf(out, "%%PDF-%d.%d\n", xref->version / 10, xref->version % 10);
- fprintf(out, "%%\316\274\341\277\246\n\n");
-
- uselist = fz_malloc_array(ctx, xref->len + 1, sizeof(char));
- ofslist = fz_malloc_array(ctx, xref->len + 1, sizeof(int));
- genlist = fz_malloc_array(ctx, xref->len + 1, sizeof(int));
- renumbermap = fz_malloc_array(ctx, xref->len + 1, sizeof(int));
-
- for (num = 0; num < xref->len; num++)
- {
- uselist[num] = 0;
- ofslist[num] = 0;
- genlist[num] = 0;
- renumbermap[num] = num;
- }
-
- /* Make sure any objects hidden in compressed streams have been loaded */
- preloadobjstms();
-
/* Only retain the specified subset of the pages */
if (subset)
retainpages(argc, argv);
- /* Sweep & mark objects from the trailer */
- if (dogarbage >= 1)
- sweepobj(xref->trailer);
-
- /* Coalesce and renumber duplicate objects */
- if (dogarbage >= 3)
- removeduplicateobjs();
-
- /* Compact xref by renumbering and removing unused objects */
- if (dogarbage >= 2)
- compactxref();
-
- /* Make renumbering affect all indirect references and update xref */
- /* Do not renumber objects if encryption is in use, as the object
- * numbers are baked into the streams/strings, and we can't currently
- * cope with moving them. See bug 692627. */
- if (dogarbage >= 2 && !xref->crypt)
- renumberobjs();
-
- writepdf();
-
- if (fclose(out))
- fz_throw(ctx, "cannot close output file '%s'", outfile);
-
- fz_free(xref->ctx, uselist);
- fz_free(xref->ctx, ofslist);
- fz_free(xref->ctx, genlist);
- fz_free(xref->ctx, renumbermap);
+ pdf_write_document(xref, outfile, &opts);
pdf_close_document(xref);
fz_free_context(ctx);
diff --git a/apps/mupdfextract.c b/apps/mupdfextract.c
index a6a677cd..8db6ceaf 100644
--- a/apps/mupdfextract.c
+++ b/apps/mupdfextract.c
@@ -3,6 +3,7 @@
*/
#include "mupdf.h"
+#include "mupdf-internal.h"
static pdf_document *doc = NULL;
static fz_context *ctx = NULL;
@@ -10,7 +11,7 @@ static int dorgb = 0;
static void usage(void)
{
- fprintf(stderr, "usage: pdfextract [options] file.pdf [object numbers]\n");
+ fprintf(stderr, "usage: mubusy extract [options] file.pdf [object numbers]\n");
fprintf(stderr, "\t-p\tpassword\n");
fprintf(stderr, "\t-r\tconvert images to rgb\n");
exit(1);
@@ -142,11 +143,7 @@ static void showobject(int num)
pdf_drop_obj(obj);
}
-#ifdef MUPDF_COMBINED_EXE
int pdfextract_main(int argc, char **argv)
-#else
-int main(int argc, char **argv)
-#endif
{
char *infile;
char *password = "";
@@ -174,7 +171,7 @@ int main(int argc, char **argv)
exit(1);
}
- doc = pdf_open_document(ctx, infile);
+ doc = pdf_open_document_no_run(ctx, infile);
if (pdf_needs_password(doc))
if (!pdf_authenticate_password(doc, password))
fz_throw(ctx, "cannot authenticate password: %s", infile);
diff --git a/apps/mupdfinfo.c b/apps/mupdfinfo.c
index ace390a6..6e4db812 100644
--- a/apps/mupdfinfo.c
+++ b/apps/mupdfinfo.c
@@ -154,7 +154,7 @@ static void
infousage(void)
{
fprintf(stderr,
- "usage: pdfinfo [options] [file.pdf ... ]\n"
+ "usage: mubusy info [options] [file.pdf ... ]\n"
"\t-d -\tpassword for decryption\n"
"\t-f\tlist fonts\n"
"\t-i\tlist images\n"
@@ -552,7 +552,7 @@ gatherpatterns(int page, pdf_obj *pageref, pdf_obj *pageobj, pdf_obj *dict)
}
static void
-gatherresourceinfo(int page, pdf_obj *rsrc)
+gatherresourceinfo(int page, pdf_obj *rsrc, int show)
{
pdf_obj *pageobj;
pdf_obj *pageref;
@@ -570,7 +570,7 @@ gatherresourceinfo(int page, pdf_obj *rsrc)
fz_throw(ctx, "cannot retrieve info from page %d", page);
font = pdf_dict_gets(rsrc, "Font");
- if (font)
+ if (show & FONTS && font)
{
int n;
@@ -582,12 +582,12 @@ gatherresourceinfo(int page, pdf_obj *rsrc)
subrsrc = pdf_dict_gets(obj, "Resources");
if (subrsrc && pdf_objcmp(rsrc, subrsrc))
- gatherresourceinfo(page, subrsrc);
+ gatherresourceinfo(page, subrsrc, show);
}
}
xobj = pdf_dict_gets(rsrc, "XObject");
- if (xobj)
+ if (show & XOBJS && xobj)
{
int n;
@@ -600,16 +600,16 @@ gatherresourceinfo(int page, pdf_obj *rsrc)
pdf_obj *obj = pdf_dict_get_val(xobj, i);
subrsrc = pdf_dict_gets(obj, "Resources");
if (subrsrc && pdf_objcmp(rsrc, subrsrc))
- gatherresourceinfo(page, subrsrc);
+ gatherresourceinfo(page, subrsrc, show);
}
}
shade = pdf_dict_gets(rsrc, "Shading");
- if (shade)
+ if (show & SHADINGS && shade)
gathershadings(page, pageref, pageobj, shade);
pattern = pdf_dict_gets(rsrc, "Pattern");
- if (pattern)
+ if (show & PATTERNS && pattern)
{
int n;
gatherpatterns(page, pageref, pageobj, pattern);
@@ -619,13 +619,13 @@ gatherresourceinfo(int page, pdf_obj *rsrc)
pdf_obj *obj = pdf_dict_get_val(pattern, i);
subrsrc = pdf_dict_gets(obj, "Resources");
if (subrsrc && pdf_objcmp(rsrc, subrsrc))
- gatherresourceinfo(page, subrsrc);
+ gatherresourceinfo(page, subrsrc, show);
}
}
}
static void
-gatherpageinfo(int page)
+gatherpageinfo(int page, int show)
{
pdf_obj *pageobj;
pdf_obj *pageref;
@@ -640,7 +640,7 @@ gatherpageinfo(int page)
gatherdimensions(page, pageref, pageobj);
rsrc = pdf_dict_gets(pageobj, "Resources");
- gatherresourceinfo(page, rsrc);
+ gatherresourceinfo(page, rsrc, show);
}
static void
@@ -882,12 +882,14 @@ showinfo(char *filename, int show, char *pagelist)
int page, spage, epage;
char *spec, *dash;
int allpages;
+ int pagecount;
if (!xref)
infousage();
allpages = !strcmp(pagelist, "1-");
+ pagecount = pdf_count_pages(xref);
spec = fz_strsep(&pagelist, ",");
while (spec)
{
@@ -909,26 +911,19 @@ showinfo(char *filename, int show, char *pagelist)
if (spage > epage)
page = spage, spage = epage, epage = page;
- if (spage < 1)
- spage = 1;
- if (epage > pagecount)
- epage = pagecount;
- if (spage > pagecount)
- spage = pagecount;
+ spage = CLAMP(spage, 1, pagecount);
+ epage = CLAMP(epage, 1, pagecount);
if (allpages)
printf("Retrieving info from pages %d-%d...\n", spage, epage);
- if (spage >= 1)
+ for (page = spage; page <= epage; page++)
{
- for (page = spage; page <= epage; page++)
+ gatherpageinfo(page, show);
+ if (!allpages)
{
- gatherpageinfo(page);
- if (!allpages)
- {
- printf("Page %d:\n", page);
- printinfo(filename, show, page);
- printf("\n");
- }
+ printf("Page %d:\n", page);
+ printinfo(filename, show, page);
+ printf("\n");
}
}
@@ -951,11 +946,7 @@ static int arg_is_page_range(const char *arg)
return 1;
}
-#ifdef MUPDF_COMBINED_EXE
int pdfinfo_main(int argc, char **argv)
-#else
-int main(int argc, char **argv)
-#endif
{
enum { NO_FILE_OPENED, NO_INFO_GATHERED, INFO_SHOWN } state;
char *filename = "";
@@ -1005,7 +996,7 @@ int main(int argc, char **argv)
filename = argv[fz_optind];
printf("%s:\n", filename);
- xref = pdf_open_document(ctx, filename);
+ xref = pdf_open_document_no_run(ctx, filename);
if (pdf_needs_password(xref))
if (!pdf_authenticate_password(xref, password))
fz_throw(ctx, "cannot authenticate password: %s", filename);
diff --git a/apps/mupdfposter.c b/apps/mupdfposter.c
new file mode 100644
index 00000000..317c2c5d
--- /dev/null
+++ b/apps/mupdfposter.c
@@ -0,0 +1,184 @@
+/*
+ * PDF cleaning tool: general purpose pdf syntax washer.
+ *
+ * Rewrite PDF with pretty printed objects.
+ * Garbage collect unreachable objects.
+ * Inflate compressed streams.
+ * Create subset documents.
+ *
+ * TODO: linearize document for fast web view
+ */
+
+#include "fitz.h"
+#include "mupdf-internal.h"
+
+static int x_factor = 0;
+static int y_factor = 0;
+
+static void usage(void)
+{
+ fprintf(stderr,
+ "usage: mubusy poster [options] input.pdf [output.pdf]\n"
+ "\t-p -\tpassword\n"
+ "\t-x\tx decimation factor\n"
+ "\t-y\ty decimation factor\n");
+ exit(1);
+}
+
+/*
+ * Recreate page tree to only retain specified pages.
+ */
+
+static void decimatepages(pdf_document *xref)
+{
+ pdf_obj *oldroot, *root, *pages, *kids, *parent;
+ fz_context *ctx = xref->ctx;
+ int num_pages = pdf_count_pages(xref);
+ int page, kidcount;
+
+ /* Keep only pages/type and (reduced) dest entries to avoid
+ * references to unretained pages */
+ oldroot = pdf_dict_gets(xref->trailer, "Root");
+ pages = pdf_dict_gets(oldroot, "Pages");
+
+ root = pdf_new_dict(ctx, 2);
+ pdf_dict_puts(root, "Type", pdf_dict_gets(oldroot, "Type"));
+ pdf_dict_puts(root, "Pages", pdf_dict_gets(oldroot, "Pages"));
+
+ pdf_update_object(xref, pdf_to_num(oldroot), root);
+
+ pdf_drop_obj(root);
+
+ /* Create a new kids array with only the pages we want to keep */
+ parent = pdf_new_indirect(ctx, pdf_to_num(pages), pdf_to_gen(pages), xref);
+ kids = pdf_new_array(ctx, 1);
+
+ kidcount = 0;
+ for (page=0; page < num_pages; page++)
+ {
+ pdf_page *page_details = pdf_load_page(xref, page);
+ int xf = x_factor, yf = y_factor;
+ int x, y;
+ float w = page_details->mediabox.x1 - page_details->mediabox.x0;
+ float h = page_details->mediabox.y1 - page_details->mediabox.y0;
+
+ if (xf == 0 && yf == 0)
+ {
+ /* Nothing specified, so split along the long edge */
+ if (w > h)
+ xf = 2, yf = 1;
+ else
+ xf = 1, yf = 2;
+ }
+ else if (xf == 0)
+ xf = 1;
+ else if (yf == 0)
+ yf = 1;
+
+ for (y = yf-1; y >= 0; y--)
+ {
+ for (x = 0; x < xf; x++)
+ {
+ pdf_obj *newpageobj, *newpageref, *newmediabox;
+ fz_rect mb;
+ int num;
+
+ newpageobj = pdf_copy_dict(ctx, xref->page_objs[page]);
+ num = pdf_create_object(xref);
+ pdf_update_object(xref, num, newpageobj);
+ newpageref = pdf_new_indirect(ctx, num, 0, xref);
+
+ newmediabox = pdf_new_array(ctx, 4);
+
+ mb.x0 = page_details->mediabox.x0 + (w/xf)*x;
+ if (x == xf-1)
+ mb.x1 = page_details->mediabox.x1;
+ else
+ mb.x1 = page_details->mediabox.x0 + (w/xf)*(x+1);
+ mb.y0 = page_details->mediabox.y0 + (h/yf)*y;
+ if (y == yf-1)
+ mb.y1 = page_details->mediabox.y1;
+ else
+ mb.y1 = page_details->mediabox.y0 + (h/yf)*(y+1);
+
+ pdf_array_push(newmediabox, pdf_new_real(ctx, mb.x0));
+ pdf_array_push(newmediabox, pdf_new_real(ctx, mb.y0));
+ pdf_array_push(newmediabox, pdf_new_real(ctx, mb.x1));
+ pdf_array_push(newmediabox, pdf_new_real(ctx, mb.y1));
+
+ pdf_dict_puts(newpageobj, "Parent", parent);
+ pdf_dict_puts(newpageobj, "MediaBox", newmediabox);
+
+ /* Store page object in new kids array */
+ pdf_array_push(kids, newpageref);
+
+ kidcount++;
+ }
+ }
+ }
+
+ pdf_drop_obj(parent);
+
+ /* Update page count and kids array */
+ pdf_dict_puts(pages, "Count", pdf_new_int(ctx, kidcount));
+ pdf_dict_puts(pages, "Kids", kids);
+ pdf_drop_obj(kids);
+}
+
+int pdfposter_main(int argc, char **argv)
+{
+ char *infile;
+ char *outfile = "out.pdf";
+ char *password = "";
+ int c;
+ fz_write_options opts;
+ pdf_document *xref;
+ fz_context *ctx;
+
+ opts.dogarbage = 0;
+ opts.doexpand = 0;
+ opts.doascii = 0;
+
+ while ((c = fz_getopt(argc, argv, "x:y:")) != -1)
+ {
+ switch (c)
+ {
+ case 'p': password = fz_optarg; break;
+ case 'x': x_factor = atoi(fz_optarg); break;
+ case 'y': y_factor = atoi(fz_optarg); break;
+ default: usage(); break;
+ }
+ }
+
+ if (argc - fz_optind < 1)
+ usage();
+
+ infile = argv[fz_optind++];
+
+ if (argc - fz_optind > 0 &&
+ (strstr(argv[fz_optind], ".pdf") || strstr(argv[fz_optind], ".PDF")))
+ {
+ outfile = argv[fz_optind++];
+ }
+
+ ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
+ if (!ctx)
+ {
+ fprintf(stderr, "cannot initialise context\n");
+ exit(1);
+ }
+
+ xref = pdf_open_document_no_run(ctx, infile);
+ if (pdf_needs_password(xref))
+ if (!pdf_authenticate_password(xref, password))
+ fz_throw(ctx, "cannot authenticate password: %s", infile);
+
+ /* Only retain the specified subset of the pages */
+ decimatepages(xref);
+
+ pdf_write_document(xref, outfile, &opts);
+
+ pdf_close_document(xref);
+ fz_free_context(ctx);
+ return 0;
+}
diff --git a/apps/mupdfshow.c b/apps/mupdfshow.c
index 70ca7a62..252e7dc2 100644
--- a/apps/mupdfshow.c
+++ b/apps/mupdfshow.c
@@ -12,7 +12,7 @@ static int showcolumn;
static void usage(void)
{
- fprintf(stderr, "usage: pdfshow [options] file.pdf [grepable] [xref] [trailer] [pagetree] [object numbers]\n");
+ fprintf(stderr, "usage: mubusy show [options] file.pdf [grepable] [xref] [trailer] [pagetree] [object numbers]\n");
fprintf(stderr, "\t-b\tprint streams as binary data\n");
fprintf(stderr, "\t-e\tprint encoded streams (don't decode)\n");
fprintf(stderr, "\t-p\tpassword\n");
@@ -171,11 +171,7 @@ static void showgrep(char *filename)
pdf_fprint_obj(stdout, doc->trailer, 1);
}
-#ifdef MUPDF_COMBINED_EXE
int pdfshow_main(int argc, char **argv)
-#else
-int main(int argc, char **argv)
-#endif
{
char *password = NULL; /* don't throw errors if encrypted */
char *filename;
@@ -207,10 +203,10 @@ int main(int argc, char **argv)
fz_var(doc);
fz_try(ctx)
{
- doc = pdf_open_document(ctx, filename);
+ doc = pdf_open_document_no_run(ctx, filename);
if (pdf_needs_password(doc))
if (!pdf_authenticate_password(doc, password))
- fz_throw(ctx, "cannot authenticate password: %s", filename);
+ fz_warn(ctx, "cannot authenticate password: %s", filename);
if (fz_optind == argc)
showtrailer();
diff --git a/apps/pdfapp.c b/apps/pdfapp.c
index eb39c6fa..b5b28867 100644
--- a/apps/pdfapp.c
+++ b/apps/pdfapp.c
@@ -227,7 +227,10 @@ static void pdfapp_panview(pdfapp_t *app, int newx, int newy)
static void pdfapp_loadpage(pdfapp_t *app)
{
- fz_device *mdev;
+ fz_device *mdev = NULL;
+ int errored = 0;
+
+ fz_var(mdev);
if (app->page_list)
fz_free_display_list(app->ctx, app->page_list);
@@ -245,23 +248,48 @@ static void pdfapp_loadpage(pdfapp_t *app)
app->page_sheet = NULL;
app->page_links = NULL;
app->page = NULL;
+ app->page_bbox.x0 = 0;
+ app->page_bbox.y0 = 0;
+ app->page_bbox.x1 = 100;
+ app->page_bbox.y1 = 100;
fz_try(app->ctx)
{
app->page = fz_load_page(app->doc, app->pageno - 1);
+ app->page_bbox = fz_bound_page(app->doc, app->page);
+ }
+ fz_catch(app->ctx)
+ {
+ pdfapp_warn(app, "Cannot load page");
+ return;
+ }
+
+ fz_try(app->ctx)
+ {
/* Create display list */
app->page_list = fz_new_display_list(app->ctx);
mdev = fz_new_list_device(app->ctx, app->page_list);
fz_run_page(app->doc, app->page, mdev, fz_identity, NULL);
+ }
+ fz_always(app->ctx)
+ {
fz_free_device(mdev);
+ }
+ fz_catch(app->ctx)
+ {
+ pdfapp_warn(app, "Cannot load page");
+ errored = 1;
+ }
- app->page_bbox = fz_bound_page(app->doc, app->page);
+ fz_try(app->ctx)
+ {
app->page_links = fz_load_links(app->doc, app->page);
}
fz_catch(app->ctx)
{
- pdfapp_error(app, "cannot load page");
+ if (!errored)
+ pdfapp_warn(app, "Cannot load page");
}
}
diff --git a/apps/x11_main.c b/apps/x11_main.c
index 6ab5b43a..941afcfa 100644
--- a/apps/x11_main.c
+++ b/apps/x11_main.c
@@ -59,6 +59,7 @@ extern void ximage_blit(Drawable d, GC gc, int dstx, int dsty,
int srcx, int srcy, int srcw, int srch, int srcstride);
void windrawstringxor(pdfapp_t *app, int x, int y, char *s);
+void cleanup(pdfapp_t *app);
static Display *xdpy;
static Atom XA_TARGETS;
@@ -100,6 +101,7 @@ static int showingpage = 0;
void winerror(pdfapp_t *app, char *msg)
{
fprintf(stderr, "mupdf: error: %s\n", msg);
+ cleanup(app);
exit(1);
}
@@ -215,6 +217,27 @@ void winclose(pdfapp_t *app)
closing = 1;
}
+void cleanup(pdfapp_t *app)
+{
+ fz_context *ctx = app->ctx;
+
+ pdfapp_close(app);
+
+ XDestroyWindow(xdpy, xwin);
+
+ XFreePixmap(xdpy, xicon);
+
+ XFreeCursor(xdpy, xcwait);
+ XFreeCursor(xdpy, xchand);
+ XFreeCursor(xdpy, xcarrow);
+
+ XFreeGC(xdpy, xgc);
+
+ XCloseDisplay(xdpy);
+
+ fz_free_context(ctx);
+}
+
static int winresolution()
{
return DisplayWidth(xdpy, xscr) * 25.4 /
@@ -825,21 +848,7 @@ int main(int argc, char **argv)
}
}
- pdfapp_close(&gapp);
-
- XDestroyWindow(xdpy, xwin);
-
- XFreePixmap(xdpy, xicon);
-
- XFreeCursor(xdpy, xcwait);
- XFreeCursor(xdpy, xchand);
- XFreeCursor(xdpy, xcarrow);
-
- XFreeGC(xdpy, xgc);
-
- XCloseDisplay(xdpy);
-
- fz_free_context(ctx);
+ cleanup(&gapp);
return 0;
}
diff --git a/draw/draw_affine.c b/draw/draw_affine.c
index 4e21ced0..52b8a847 100644
--- a/draw/draw_affine.c
+++ b/draw/draw_affine.c
@@ -653,14 +653,18 @@ fz_paint_image_imp(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *shape, fz_pixmap
inv = fz_concat(inv, ctm);
inv = fz_invert_matrix(inv);
- fa = inv.a * 65536;
- fb = inv.b * 65536;
- fc = inv.c * 65536;
- fd = inv.d * 65536;
+ fa = (int)(inv.a *= 65536.0f);
+ fb = (int)(inv.b *= 65536.0f);
+ fc = (int)(inv.c *= 65536.0f);
+ fd = (int)(inv.d *= 65536.0f);
+ inv.e *= 65536.0f;
+ inv.f *= 65536.0f;
/* Calculate initial texture positions. Do a half step to start. */
- u = (fa * x) + (fc * y) + inv.e * 65536 + ((fa + fc) >> 1);
- v = (fb * x) + (fd * y) + inv.f * 65536 + ((fb + fd) >> 1);
+ /* Bug 693021: Keep calculation in float for as long as possible to
+ * avoid overflow. */
+ u = (int)((inv.a * x) + (inv.c * y) + inv.e + ((inv.a + inv.c) * .5f));
+ v = (int)((inv.b * x) + (inv.d * y) + inv.f + ((inv.b + inv.d) * .5f));
/* RJW: The following is voodoo. No idea why it works, but it gives
* the best match between scaled/unscaled/interpolated/non-interpolated
diff --git a/draw/draw_simple_scale.c b/draw/draw_simple_scale.c
index 8143b6fd..6f123ce3 100644
--- a/draw/draw_simple_scale.c
+++ b/draw/draw_simple_scale.c
@@ -807,17 +807,18 @@ scale_row_from_temp(unsigned char *dst, unsigned char *src, fz_weights *weights,
" @ r14= len = *contrib \n"
"blt 4f @ while (x >= 0) { \n"
#ifndef ARCH_ARM_CAN_LOAD_UNALIGNED
- "tst r3, #3 @ if (r3 & 3) \n"
- "blt 4f @ can't do fast code \n"
+ "tst r3, #3 @ if ((r3 & 3) \n"
+ "tsteq r1, #3 @ || (r1 & 3)) \n"
+ "bne 4f @ can't do fast code \n"
#endif
"ldr r9, =0x00FF00FF @ r9 = 0x00FF00FF \n"
"1: \n"
- "ldr r5, =0x00800080 @ r5 = val0 = round \n"
- "stmfd r13!,{r1,r2} @ stash r1,r2,r14 \n"
+ "ldr r7, =0x00800080 @ r5 = val0 = round \n"
+ "stmfd r13!,{r1,r2,r7} @ stash r1,r2,r5 \n"
" @ r1 = min = src \n"
" @ r2 = contrib2-4 \n"
"movs r8, r14 @ r8 = len2 = len \n"
- "mov r7, r5 @ r7 = val1 = round \n"
+ "mov r5, r7 @ r7 = val1 = round \n"
"ble 3f @ while (len2-- > 0) { \n"
"2: \n"
"ldr r12,[r1], r3 @ r12 = *min r5 = min += width\n"
@@ -828,11 +829,11 @@ scale_row_from_temp(unsigned char *dst, unsigned char *src, fz_weights *weights,
"mla r5, r10,r11,r5 @ r5 = val0 += r11 * r10\n"
"mla r7, r10,r12,r7 @ r7 = val1 += r12 * r10\n"
"bgt 2b @ } \n"
- "3: \n"
- "ldmfd r13!,{r1,r2} @ restore r1,r2,r14 \n"
"and r5, r9, r5, LSR #8 @ r5 = __22__00 \n"
"and r7, r7, r9, LSL #8 @ r7 = 33__11__ \n"
"orr r5, r5, r7 @ r5 = 33221100 \n"
+ "3: \n"
+ "ldmfd r13!,{r1,r2,r7} @ restore r1,r2,r7 \n"
"subs r6, r6, #4 @ x-- \n"
"add r1, r1, #4 @ src++ \n"
"str r5, [r0], #4 @ *dst++ = val \n"
diff --git a/fitz/doc_document.c b/fitz/doc_document.c
index 07319d1d..74192908 100644
--- a/fitz/doc_document.c
+++ b/fitz/doc_document.c
@@ -136,3 +136,10 @@ fz_interactive *fz_interact(fz_document *doc)
return doc->interact(doc);
return NULL;
}
+
+void
+fz_write(fz_document *doc, char *filename, fz_write_options *opts)
+{
+ if (doc && doc->write)
+ doc->write(doc, filename, opts);
+}
diff --git a/fitz/filt_basic.c b/fitz/filt_basic.c
index 09d63402..7d504f29 100644
--- a/fitz/filt_basic.c
+++ b/fitz/filt_basic.c
@@ -14,6 +14,7 @@ struct null_filter
{
fz_stream *chain;
int remain;
+ int pos;
};
static int
@@ -21,8 +22,12 @@ read_null(fz_stream *stm, unsigned char *buf, int len)
{
struct null_filter *state = stm->state;
int amount = MIN(len, state->remain);
- int n = fz_read(state->chain, buf, amount);
+ int n;
+
+ fz_seek(state->chain, state->pos, 0);
+ n = fz_read(state->chain, buf, amount);
state->remain -= n;
+ state->pos += n;
return n;
}
@@ -36,7 +41,7 @@ close_null(fz_context *ctx, void *state_)
}
fz_stream *
-fz_open_null(fz_stream *chain, int len)
+fz_open_null(fz_stream *chain, int len, int offset)
{
struct null_filter *state;
fz_context *ctx = chain->ctx;
@@ -46,6 +51,7 @@ fz_open_null(fz_stream *chain, int len)
state = fz_malloc_struct(ctx, struct null_filter);
state->chain = chain;
state->remain = len;
+ state->pos = offset;
}
fz_catch(ctx)
{
@@ -56,6 +62,104 @@ fz_open_null(fz_stream *chain, int len)
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;
+
+ fz_try(ctx)
+ {
+ 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 */
+ }
+ fz_catch(ctx)
+ {
+ fz_rethrow(ctx);
+ }
+
+ 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, "Concat filter size exceeded");
+
+ state->chain[state->count++] = chain;
+}
+
/* ASCII Hex Decode */
typedef struct fz_ahxd_s fz_ahxd;
diff --git a/fitz/filt_faxd.c b/fitz/filt_faxd.c
index ada7e87b..febc6a65 100644
--- a/fitz/filt_faxd.c
+++ b/fitz/filt_faxd.c
@@ -57,7 +57,7 @@ enum
};
/* White decoding table. */
-const cfd_node cf_white_decode[] = {
+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},
@@ -95,7 +95,7 @@ const cfd_node cf_white_decode[] = {
};
/* Black decoding table. */
-const cfd_node cf_black_decode[] = {
+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},
@@ -134,7 +134,7 @@ const cfd_node cf_black_decode[] = {
};
/* 2-D decoding table. */
-const cfd_node cf_2d_decode[] = {
+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},
@@ -153,7 +153,7 @@ const cfd_node cf_2d_decode[] = {
};
/* Uncompressed decoding table. */
-const cfd_node cf_uncompressed_decode[] = {
+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},
diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h
index 9dded182..21eb476d 100644
--- a/fitz/fitz-internal.h
+++ b/fitz/fitz-internal.h
@@ -411,7 +411,9 @@ void fz_grow_buffer(fz_context *ctx, fz_buffer *buf);
void fz_trim_buffer(fz_context *ctx, fz_buffer *buf);
/*
- fz_buffer_printf: print formatted to a buffer, growing if necessary
+ fz_buffer_printf: print formatted to a buffer. The buffer will
+ grow, but the caller must ensure that no more than 256 bytes are
+ added to the buffer per call.
*/
void fz_buffer_printf(fz_context *ctx, fz_buffer *buffer, char *fmt, ...);
@@ -424,7 +426,6 @@ struct fz_stream_s
int pos;
int avail;
int bits;
- int locked;
unsigned char *bp, *rp, *wp, *ep;
void *state;
int (*read)(fz_stream *stm, unsigned char *buf, int len);
@@ -433,8 +434,6 @@ struct fz_stream_s
unsigned char buf[4096];
};
-void fz_lock_stream(fz_stream *stm);
-
fz_stream *fz_new_stream(fz_context *ctx, void*, int(*)(fz_stream*, unsigned char*, int), void(*)(fz_context *, void *));
fz_stream *fz_keep_stream(fz_stream *stm);
void fz_fill_buffer(fz_stream *stm);
@@ -525,7 +524,9 @@ static inline int fz_is_eof_bits(fz_stream *stm)
*/
fz_stream *fz_open_copy(fz_stream *chain);
-fz_stream *fz_open_null(fz_stream *chain, int len);
+fz_stream *fz_open_null(fz_stream *chain, int len, int offset);
+fz_stream *fz_open_concat(fz_context *ctx, int max, int pad);
+void fz_concat_push(fz_stream *concat, fz_stream *chain); /* Ownership of chain is passed in */
fz_stream *fz_open_arc4(fz_stream *chain, unsigned char *key, unsigned keylen);
fz_stream *fz_open_aesd(fz_stream *chain, unsigned char *key, unsigned keylen);
fz_stream *fz_open_a85d(fz_stream *chain);
@@ -1091,6 +1092,7 @@ struct fz_document_s
void (*free_page)(fz_document *doc, fz_page *page);
int (*meta)(fz_document *doc, int key, void *ptr, int size);
fz_interactive *(*interact)(fz_document *doc);
+ void (*write)(fz_document *doc, char *filename, fz_write_options *opts);
};
#endif
diff --git a/fitz/fitz.h b/fitz/fitz.h
index d8afce95..41b1881c 100644
--- a/fitz/fitz.h
+++ b/fitz/fitz.h
@@ -92,19 +92,32 @@ int gettimeofday(struct timeval *tv, struct timezone *tz);
/*
Variadic macros, inline and restrict keywords
+
+ inline is standard in C++, so don't touch the definition in this case.
+ For some compilers we can enable it within C too.
*/
+#ifndef __cplusplus
#if __STDC_VERSION__ == 199901L /* C99 */
-#elif defined __cplusplus
-#define restrict
#elif _MSC_VER >= 1500 /* MSVC 9 or newer */
#define inline __inline
-#define restrict __restrict
#elif __GNUC__ >= 3 /* GCC 3 or newer */
#define inline __inline
-#define restrict __restrict
#else /* Unknown or ancient */
#define inline
+#endif
+#endif
+
+/*
+ restrict is standard in C99, but not in all C++ compilers. Enable
+ where possible, disable if in doubt.
+ */
+#if __STDC_VERSION__ == 199901L /* C99 */
+#elif _MSC_VER >= 1500 /* MSVC 9 or newer */
+#define restrict __restrict
+#elif __GNUC__ >= 3 /* GCC 3 or newer */
+#define restrict __restrict
+#else /* Unknown or ancient */
#define restrict
#endif
@@ -2363,4 +2376,51 @@ char *fz_widget_text_get_text(fz_widget_text *tw);
*/
void fz_widget_text_set_text(fz_widget_text *tw, char *text);
+
+typedef struct fz_write_options_s fz_write_options;
+
+/*
+ In calls to fz_write, the following options structure can be used
+ to control aspects of the writing process. This structure may grow
+ in future, and should be zero-filled to allow forwards compatiblity.
+*/
+struct fz_write_options_s
+{
+ int doascii; /* If non-zero then attempt (where possible) to
+ make the output ascii. */
+ int doexpand; /* Bitflags; each non zero bit indicates an aspect
+ of the file that should be 'expanded' on
+ writing. */
+ int dogarbage; /* If non-zero then attempt (where possible) to
+ garbage collect the file before writing. */
+};
+
+/* An enumeration of bitflags to use in the above 'doexpand' field of
+ fz_write_options.
+*/
+enum
+{
+ fz_expand_images = 1,
+ fz_expand_fonts = 2,
+ fz_expand_all = -1
+};
+
+/*
+ fz_write: Write a document out.
+
+ (In development - Subject to change in future versions)
+
+ Save a copy of the current document in its original format.
+ Internally the document may change.
+
+ doc: The document to save.
+
+ filename: The filename to save to.
+
+ opts: NULL, or a pointer to an options structure.
+
+ May throw exceptions.
+*/
+void fz_write(fz_document *doc, char *filename, fz_write_options *opts);
+
#endif
diff --git a/fitz/res_font.c b/fitz/res_font.c
index a0c2fc2a..966cbc6e 100644
--- a/fitz/res_font.c
+++ b/fitz/res_font.c
@@ -56,7 +56,7 @@ fz_new_font(fz_context *ctx, char *name, int use_glyph_bbox, int glyph_count)
else
{
if (use_glyph_bbox)
- fz_warn(ctx, "not building glyph bbox table for font '%s' with %d glyphs", name, glyph_count);
+ 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;
}
@@ -692,7 +692,7 @@ static fz_rect
fz_bound_t3_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm)
{
fz_matrix ctm;
- fz_buffer *contents;
+ void *contents;
fz_rect bounds;
fz_bbox bbox;
fz_device *dev;
@@ -726,7 +726,7 @@ fz_pixmap *
fz_render_t3_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix trm, fz_colorspace *model)
{
fz_matrix ctm;
- fz_buffer *contents;
+ void *contents;
fz_bbox bbox;
fz_device *dev;
fz_pixmap *glyph;
@@ -786,7 +786,7 @@ void
fz_render_t3_glyph_direct(fz_context *ctx, fz_device *dev, fz_font *font, int gid, fz_matrix trm, void *gstate)
{
fz_matrix ctm;
- fz_buffer *contents;
+ void *contents;
if (gid < 0 || gid > 255)
return;
diff --git a/fitz/stm_buffer.c b/fitz/stm_buffer.c
index 9b7a542c..7be824f9 100644
--- a/fitz/stm_buffer.c
+++ b/fitz/stm_buffer.c
@@ -82,19 +82,14 @@ fz_buffer_storage(fz_context *ctx, fz_buffer *buf, unsigned char **datap)
void
fz_buffer_printf(fz_context *ctx, fz_buffer *buffer, char *fmt, ...)
{
- int count;
- int done = 0;
va_list args;
va_start(args, fmt);
- while(!done)
- {
- count = vsnprintf(buffer->data + buffer->len, buffer->cap - buffer->len, fmt, args);
- done = (count >= 0 && count < buffer->cap - buffer->len);
- if (!done)
- fz_grow_buffer(ctx, buffer);
- }
+ /* Caller guarantees not to generate more than 256 bytes per call */
+ while(buffer->cap - buffer->len < 256)
+ fz_grow_buffer(ctx, buffer);
+
+ buffer->len += vsprintf(buffer->data + buffer->len, fmt, args);
- buffer->len += count;
va_end(args);
}
diff --git a/fitz/stm_open.c b/fitz/stm_open.c
index ced32d80..be069fb9 100644
--- a/fitz/stm_open.c
+++ b/fitz/stm_open.c
@@ -24,7 +24,6 @@ fz_new_stream(fz_context *ctx, void *state,
stm->bits = 0;
stm->avail = 0;
- stm->locked = 0;
stm->bp = stm->buf;
stm->rp = stm->bp;
@@ -40,16 +39,6 @@ fz_new_stream(fz_context *ctx, void *state,
return stm;
}
-void
-fz_lock_stream(fz_stream *stm)
-{
- if (stm)
- {
- fz_lock(stm->ctx, FZ_LOCK_FILE);
- stm->locked = 1;
- }
-}
-
fz_stream *
fz_keep_stream(fz_stream *stm)
{
@@ -67,8 +56,6 @@ fz_close(fz_stream *stm)
{
if (stm->close)
stm->close(stm->ctx, stm->state);
- if (stm->locked)
- fz_unlock(stm->ctx, FZ_LOCK_FILE);
fz_free(stm->ctx, stm);
}
}
@@ -78,7 +65,6 @@ fz_close(fz_stream *stm)
static int read_file(fz_stream *stm, unsigned char *buf, int len)
{
int n = read(*(int*)stm->state, buf, len);
- fz_assert_lock_held(stm->ctx, FZ_LOCK_FILE);
if (n < 0)
fz_throw(stm->ctx, "read error: %s", strerror(errno));
return n;
@@ -87,7 +73,6 @@ static int read_file(fz_stream *stm, unsigned char *buf, int len)
static void seek_file(fz_stream *stm, int offset, int whence)
{
int n = lseek(*(int*)stm->state, offset, whence);
- fz_assert_lock_held(stm->ctx, FZ_LOCK_FILE);
if (n < 0)
fz_throw(stm->ctx, "cannot lseek: %s", strerror(errno));
stm->pos = n;
diff --git a/ios/Info.plist b/ios/Info.plist
index 6afbcf12..1e29c114 100644
--- a/ios/Info.plist
+++ b/ios/Info.plist
@@ -48,5 +48,88 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
+ <key>CFBundleDocumentTypes</key>
+ <array>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>PDF</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>com.adobe.pdf</string>
+ </array>
+ <key>LSHandlerRank</key>
+ <string>Alternate</string>
+ </dict>
+ <dict>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>com.microsoft.xps</string>
+ </array>
+ <key>CFBundleTypeName</key>
+ <string>XPS</string>
+ <key>LSHandlerRank</key>
+ <string>Alternate</string>
+ </dict>
+ <dict>
+ <key>CFBundleTypeName</key>
+ <string>CBZ</string>
+ <key>LSItemContentTypes</key>
+ <array>
+ <string>public.zip-archive</string>
+ </array>
+ <key>LSHandlerRank</key>
+ <string>Alternate</string>
+ </dict>
+ </array>
+ <key>UTImportedTypeDeclarations</key>
+ <array>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ </array>
+ <key>UTTypeIdentifier</key>
+ <string>com.microsoft.xps</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>xps</string>
+ <string>oxps</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ </array>
+ <key>UTTypeIdentifier</key>
+ <string>public.zip-archive</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>zip</string>
+ <string>cbz</string>
+ </array>
+ </dict>
+ </dict>
+ <dict>
+ <key>UTTypeConformsTo</key>
+ <array>
+ <string>public.data</string>
+ </array>
+ <key>UTTypeIdentifier</key>
+ <string>com.adobe.pdf</string>
+ <key>UTTypeTagSpecification</key>
+ <dict>
+ <key>public.filename-extension</key>
+ <array>
+ <string>pdf</string>
+ </array>
+ </dict>
+ </dict>
+ </array>
</dict>
</plist>
diff --git a/ios/main.m b/ios/main.m
index f242aedf..f24e2bdd 100644
--- a/ios/main.m
+++ b/ios/main.m
@@ -272,10 +272,10 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
- (void) viewWillAppear: (BOOL)animated
{
- [self setTitle: @"PDF and XPS Documents"];
+ [self setTitle: @"PDF, XPS and CBZ Documents"];
[self reload];
printf("library viewWillAppear (starting reload timer)\n");
- timer = [NSTimer timerWithTimeInterval: 1
+ timer = [NSTimer timerWithTimeInterval: 3
target: self selector: @selector(reload) userInfo: nil
repeats: YES];
[[NSRunLoop currentRunLoop] addTimer: timer forMode: NSDefaultRunLoopMode];
@@ -290,18 +290,26 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
- (void) reload
{
- NSError *error = nil;
-
if (files) {
[files release];
files = nil;
}
+ NSFileManager *fileman = [NSFileManager defaultManager];
NSString *docdir = [NSString stringWithFormat: @"%@/Documents", NSHomeDirectory()];
- files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath: docdir error: &error];
- if (error)
- files = [NSArray arrayWithObjects: @"...error loading directory...", nil];
- [files retain];
+ NSMutableArray *outfiles = [[NSMutableArray alloc] init];
+ NSDirectoryEnumerator *direnum = [fileman enumeratorAtPath:docdir];
+ NSString *file;
+ BOOL isdir;
+ while (file = [direnum nextObject]) {
+ NSString *filepath = [docdir stringByAppendingPathComponent:file];
+ NSLog(@"file %@\n", file);
+ if ([fileman fileExistsAtPath:filepath isDirectory:&isdir] && !isdir) {
+ [outfiles addObject:file];
+ }
+ }
+
+ files = outfiles;
[[self tableView] reloadData];
}
@@ -1386,6 +1394,8 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
- (BOOL) application: (UIApplication*)application didFinishLaunchingWithOptions: (NSDictionary*)launchOptions
{
+ NSString *filename;
+
queue = dispatch_queue_create("com.artifex.mupdf.queue", NULL);
// use at most 128M for resource cache
@@ -1405,13 +1415,31 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
[window addSubview: [navigator view]];
[window makeKeyAndVisible];
- NSString *filename = [[NSUserDefaults standardUserDefaults] objectForKey: @"OpenDocumentKey"];
+ filename = [[NSUserDefaults standardUserDefaults] objectForKey: @"OpenDocumentKey"];
if (filename)
[library openDocument: filename];
+ filename = [launchOptions objectForKey: UIApplicationLaunchOptionsURLKey];
+ NSLog(@"urlkey = %@\n", filename);
+
return YES;
}
+- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
+{
+ NSLog(@"openURL: %@\n", url);
+ if ([url isFileURL]) {
+ NSString *path = [url path];
+ NSString *dir = [NSString stringWithFormat: @"%@/Documents/", NSHomeDirectory()];
+ path = [path stringByReplacingOccurrencesOfString:@"/private" withString:@""];
+ path = [path stringByReplacingOccurrencesOfString:dir withString:@""];
+ NSLog(@"file relative path: %@\n", path);
+ [library openDocument:path];
+ return YES;
+ }
+ return NO;
+}
+
- (void)applicationDidEnterBackground:(UIApplication *)application
{
printf("applicationDidEnterBackground!\n");
diff --git a/pdf/mupdf-internal.h b/pdf/mupdf-internal.h
index b50ba2fe..b1117726 100644
--- a/pdf/mupdf-internal.h
+++ b/pdf/mupdf-internal.h
@@ -146,11 +146,12 @@ typedef struct pdf_xref_entry_s pdf_xref_entry;
struct pdf_xref_entry_s
{
+ char type; /* 0=unset (f)ree i(n)use (o)bjstm */
int ofs; /* file offset / objstm object number */
int gen; /* generation / objstm index */
int stm_ofs; /* on-disk stream */
+ fz_buffer *stm_buf; /* in-memory stream (for updated objects) */
pdf_obj *obj; /* stored/cached object */
- int type; /* 0=unset (f)ree i(n)use (o)bjstm */
};
typedef struct pdf_crypt_s pdf_crypt;
@@ -217,19 +218,25 @@ struct pdf_document_s
pdf_js *js;
};
+pdf_document *pdf_open_document_no_run(fz_context *ctx, const char *filename);
+pdf_document *pdf_open_document_no_run_with_stream(fz_stream *file);
+
void pdf_cache_object(pdf_document *doc, int num, int gen);
fz_stream *pdf_open_inline_stream(pdf_document *doc, pdf_obj *stmobj, int length, fz_stream *chain, pdf_image_params *params);
-fz_buffer *pdf_load_image_stream(pdf_document *doc, int num, int gen, pdf_image_params *params);
-fz_stream *pdf_open_image_stream(pdf_document *doc, int num, int gen, pdf_image_params *params);
+fz_buffer *pdf_load_image_stream(pdf_document *doc, int num, int gen, int orig_num, int orig_gen, pdf_image_params *params);
+fz_stream *pdf_open_image_stream(pdf_document *doc, int num, int gen, int orig_num, int orig_gen, pdf_image_params *params);
fz_stream *pdf_open_stream_with_offset(pdf_document *doc, int num, int gen, pdf_obj *dict, int stm_ofs);
fz_stream *pdf_open_image_decomp_stream(fz_context *ctx, fz_buffer *, pdf_image_params *params, int *factor);
+fz_stream *pdf_open_contents_stream(pdf_document *xref, pdf_obj *obj);
+fz_buffer *pdf_load_raw_renumbered_stream(pdf_document *doc, int num, int gen, int orig_num, int orig_gen);
+fz_buffer *pdf_load_renumbered_stream(pdf_document *doc, int num, int gen, int orig_num, int orig_gen);
+fz_stream *pdf_open_raw_renumbered_stream(pdf_document *doc, int num, int gen, int orig_num, int orig_gen);
void pdf_repair_xref(pdf_document *doc, pdf_lexbuf *buf);
void pdf_repair_obj_stms(pdf_document *doc);
void pdf_print_xref(pdf_document *);
void pdf_resize_xref(pdf_document *doc, int newcap);
-pdf_obj *pdf_new_stream_indirection(pdf_document *doc, pdf_obj *obj);
/*
* Encryption
@@ -239,6 +246,7 @@ pdf_crypt *pdf_new_crypt(fz_context *ctx, pdf_obj *enc, pdf_obj *id);
void pdf_free_crypt(fz_context *ctx, pdf_crypt *crypt);
void pdf_crypt_obj(fz_context *ctx, pdf_crypt *crypt, pdf_obj *obj, int num, int gen);
+void pdf_crypt_buffer(fz_context *ctx, pdf_crypt *crypt, fz_buffer *buf, int num, int gen);
fz_stream *pdf_open_crypt(fz_stream *chain, pdf_crypt *crypt, int num, int gen);
fz_stream *pdf_open_crypt_with_filter(fz_stream *chain, pdf_crypt *crypt, char *name, int num, int gen);
@@ -284,7 +292,7 @@ struct pdf_pattern_s
fz_matrix matrix;
fz_rect bbox;
pdf_obj *resources;
- fz_buffer *contents;
+ pdf_obj *contents;
};
pdf_pattern *pdf_load_pattern(pdf_document *doc, pdf_obj *obj);
@@ -307,7 +315,7 @@ struct pdf_xobject_s
int transparency;
fz_colorspace *colorspace;
pdf_obj *resources;
- fz_buffer *contents;
+ pdf_obj *contents;
pdf_obj *me;
};
@@ -315,7 +323,7 @@ pdf_xobject *pdf_load_xobject(pdf_document *doc, pdf_obj *obj);
pdf_obj *pdf_new_xobject(pdf_document *doc, fz_rect *bbox, fz_matrix *mat);
pdf_xobject *pdf_keep_xobject(fz_context *ctx, pdf_xobject *xobj);
void pdf_drop_xobject(fz_context *ctx, pdf_xobject *xobj);
-void pdf_xobject_set_contents(fz_context *ctx, pdf_xobject *from, fz_buffer *buffer);
+void pdf_xobject_set_contents(pdf_document *xref, pdf_xobject *from, fz_buffer *buffer);
void pdf_update_appearance(pdf_document *doc, pdf_obj *obj);
@@ -553,7 +561,7 @@ struct pdf_page_s
int rotate;
int transparency;
pdf_obj *resources;
- fz_buffer *contents;
+ pdf_obj *contents;
fz_link *links;
pdf_annot *annots;
};
diff --git a/pdf/mupdf.h b/pdf/mupdf.h
index 2d27f4af..2d93b793 100644
--- a/pdf/mupdf.h
+++ b/pdf/mupdf.h
@@ -20,7 +20,6 @@ pdf_obj *pdf_new_real(fz_context *ctx, float f);
pdf_obj *fz_new_name(fz_context *ctx, char *str);
pdf_obj *pdf_new_string(fz_context *ctx, char *str, int len);
pdf_obj *pdf_new_indirect(fz_context *ctx, int num, int gen, void *doc);
-
pdf_obj *pdf_new_array(fz_context *ctx, int initialcap);
pdf_obj *pdf_new_dict(fz_context *ctx, int initialcap);
pdf_obj *pdf_new_rect(fz_context *ctx, fz_rect *rect);
@@ -97,7 +96,6 @@ fz_matrix pdf_to_matrix(fz_context *ctx, pdf_obj *array);
int pdf_count_objects(pdf_document *doc);
pdf_obj *pdf_resolve_indirect(pdf_obj *ref);
pdf_obj *pdf_load_object(pdf_document *doc, int num, int gen);
-void pdf_update_object(pdf_document *doc, int num, int gen, pdf_obj *newobj);
fz_buffer *pdf_load_raw_stream(pdf_document *doc, int num, int gen);
fz_buffer *pdf_load_stream(pdf_document *doc, int num, int gen);
@@ -109,6 +107,41 @@ fz_image *pdf_load_image(pdf_document *doc, pdf_obj *obj);
fz_outline *pdf_load_outline(pdf_document *doc);
/*
+ pdf_create_object: Allocate a slot in the xref table and return a fresh unused object number.
+*/
+int pdf_create_object(pdf_document *xref);
+
+/*
+ pdf_delete_object: Remove object from xref table, marking the slot as free.
+*/
+void pdf_delete_object(pdf_document *xref, int num);
+
+/*
+ pdf_update_object: Replace object in xref table with the passed in object.
+*/
+void pdf_update_object(pdf_document *xref, int num, pdf_obj *obj);
+
+/*
+ pdf_get_stream: Return the contents for object in xref table
+*/
+fz_buffer *pdf_get_stream(pdf_document *xref, int num);
+
+/*
+ pdf_update_stream: Replace stream contents for object in xref table with the passed in buffer.
+
+ The buffer contents must match the /Filter setting.
+ If storing uncompressed data, make sure to delete the /Filter key from
+ the stream dictionary. If storing deflated data, make sure to set the
+ /Filter value to /FlateDecode.
+*/
+void pdf_update_stream(pdf_document *xref, int num, fz_buffer *buf);
+
+/*
+ pdf_write_document: Write out the document to a file with all changes finalised.
+*/
+void pdf_write_document(pdf_document *doc, char *filename, fz_write_options *opts);
+
+/*
pdf_open_document: Open a PDF document.
Open a PDF document by reading its cross reference table, so
@@ -218,4 +251,9 @@ void pdf_run_page(pdf_document *doc, pdf_page *page, fz_device *dev, fz_matrix c
void pdf_run_page_with_usage(pdf_document *doc, pdf_page *page, fz_device *dev, fz_matrix ctm, char *event, fz_cookie *cookie);
+/*
+ Metadata interface.
+*/
+int pdf_meta(pdf_document *doc, int key, void *ptr, int size);
+
#endif
diff --git a/pdf/pdf_cmap.c b/pdf/pdf_cmap.c
index 71066986..1f1117fe 100644
--- a/pdf/pdf_cmap.c
+++ b/pdf/pdf_cmap.c
@@ -189,7 +189,7 @@ add_table(fz_context *ctx, pdf_cmap *cmap, int value)
}
if (cmap->tlen + 1 > cmap->tcap)
{
- int new_cap = cmap->tcap > 1 ? (cmap->tcap * 3) / 2 : 256;
+ int new_cap = cmap->tcap > 1 ? (cmap->tcap * 3) / 2 : 256;
cmap->table = fz_resize_array(ctx, cmap->table, new_cap, sizeof(unsigned short));
cmap->tcap = new_cap;
}
diff --git a/pdf/pdf_font.c b/pdf/pdf_font.c
index ab60af72..9e4e60ea 100644
--- a/pdf/pdf_font.c
+++ b/pdf/pdf_font.c
@@ -148,7 +148,7 @@ static int ft_width(fz_context *ctx, pdf_font_desc *fontdesc, int cid)
{
int gid = ft_cid_to_gid(fontdesc, cid);
int fterr;
-
+
fterr = FT_Load_Glyph(fontdesc->font->ft_face, gid,
FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM);
if (fterr)
diff --git a/pdf/pdf_form.c b/pdf/pdf_form.c
index 92eda83f..a517c339 100644
--- a/pdf/pdf_form.c
+++ b/pdf/pdf_form.c
@@ -71,6 +71,11 @@ static const char *fmt_ET = "ET\n";
static const char *fmt_Q = "Q\n";
static const char *fmt_EMC = "EMC\n";
+static fz_buffer *form_contents(pdf_document *doc, pdf_xobject *form)
+{
+ return pdf_get_stream(doc, pdf_to_num(form->contents));
+}
+
static void account_for_rot(fz_rect *rect, fz_matrix *mat, int rot)
{
float width = rect->x1;
@@ -659,8 +664,9 @@ fz_buffer *create_text_appearance(pdf_document *doc, fz_rect *bbox, fz_matrix *o
return fzbuf;
}
-static void update_marked_content(fz_context *ctx, pdf_xobject *form, fz_buffer *fzbuf)
+static void update_marked_content(pdf_document *doc, pdf_xobject *form, fz_buffer *fzbuf)
{
+ fz_context *ctx = doc->ctx;
int tok;
pdf_lexbuf lbuf;
fz_stream *str_outer = NULL;
@@ -681,7 +687,7 @@ static void update_marked_content(fz_context *ctx, pdf_xobject *form, fz_buffer
int first = 1;
newbuf = fz_new_buffer(ctx, 0);
- len = fz_buffer_storage(ctx, form->contents, &buf);
+ len = fz_buffer_storage(ctx, form_contents(doc, form), &buf);
str_outer = fz_open_memory(ctx, buf, len);
len = fz_buffer_storage(ctx, fzbuf, &buf);
str_inner = fz_open_memory(ctx, buf, len);
@@ -733,7 +739,7 @@ static void update_marked_content(fz_context *ctx, pdf_xobject *form, fz_buffer
}
/* Use newbuf in place of the existing appearance stream */
- pdf_xobject_set_contents(ctx, form, newbuf);
+ pdf_xobject_set_contents(doc, form, newbuf);
}
fz_always(ctx)
{
@@ -756,7 +762,7 @@ int get_matrix(pdf_document *doc, pdf_xobject *form, int q, fz_matrix *mt)
pdf_lexbuf lbuf;
fz_stream *str;
- bufsize = fz_buffer_storage(ctx, form->contents, &buf);
+ bufsize = fz_buffer_storage(ctx, form_contents(doc, form), &buf);
str = fz_open_memory(ctx, buf, bufsize);
memset(lbuf.scratch, 0, sizeof(lbuf.scratch));
@@ -807,7 +813,7 @@ int get_matrix(pdf_document *doc, pdf_xobject *form, int q, fz_matrix *mt)
if (q != Q_Left)
{
/* Offset the matrix to refer to the alignment position */
- fz_rect bbox = measure_text(doc, form->resources, form->contents);
+ fz_rect bbox = measure_text(doc, form->resources, form_contents(doc, form));
mt->e += q == Q_Right ? (bbox.x1 - bbox.x0)
: (bbox.x1 - bbox.x0) / 2;
}
@@ -859,7 +865,7 @@ static void update_text_appearance(pdf_document *doc, pdf_obj *obj, char *text)
has_tm = get_matrix(doc, form, q, &tm);
fzbuf = create_text_appearance(doc, &form->bbox, has_tm ? &tm : NULL, q, dr, pdf_to_str_buf(da), text);
- update_marked_content(ctx, form, fzbuf);
+ update_marked_content(doc, form, fzbuf);
}
}
}
@@ -921,7 +927,7 @@ static void synthesize_text_widget(pdf_document *doc, pdf_obj *obj)
form = pdf_load_xobject(doc, formobj);
fzbuf = fz_new_buffer(ctx, 0);
fz_buffer_printf(ctx, fzbuf, "/Tx BMC EMC");
- pdf_xobject_set_contents(ctx, form, fzbuf);
+ pdf_xobject_set_contents(doc, form, fzbuf);
ap = pdf_new_dict(ctx, 1);
pdf_dict_puts(ap, "N", formobj);
@@ -1145,7 +1151,7 @@ static void update_pushbutton_widget(pdf_document *doc, pdf_obj *obj)
fzbuf_print_text(ctx, fzbuf, &clip, da, 0, &mat, text);
}
- pdf_xobject_set_contents(ctx, form, fzbuf);
+ pdf_xobject_set_contents(doc, form, fzbuf);
}
fz_always(ctx)
{
diff --git a/pdf/pdf_image.c b/pdf/pdf_image.c
index dc9cc088..b4571bbe 100644
--- a/pdf/pdf_image.c
+++ b/pdf/pdf_image.c
@@ -95,7 +95,7 @@ static fz_store_type pdf_image_store_type =
};
static fz_pixmap *
-decomp_image_from_stream(fz_context *ctx, fz_stream *stm, pdf_image *image, int in_line, int indexed, int factor)
+decomp_image_from_stream(fz_context *ctx, fz_stream *stm, pdf_image *image, int in_line, int indexed, int factor, int cache)
{
fz_pixmap *tile = NULL;
fz_pixmap *existing_tile;
@@ -190,6 +190,9 @@ decomp_image_from_stream(fz_context *ctx, fz_stream *stm, pdf_image *image, int
fz_rethrow(ctx);
}
+ if (!cache)
+ return tile;
+
/* Now we try to cache the pixmap. Any failure here will just result
* in us not caching. */
fz_try(ctx)
@@ -279,7 +282,7 @@ pdf_image_get_pixmap(fz_context *ctx, fz_image *image_, int w, int h)
/* We need to make a new one. */
stm = pdf_open_image_decomp_stream(ctx, image->buffer, &image->params, &factor);
- return decomp_image_from_stream(ctx, stm, image, 0, 0, factor);
+ return decomp_image_from_stream(ctx, stm, image, 0, 0, factor, 1);
}
static pdf_image *
@@ -427,7 +430,9 @@ pdf_load_image_imp(pdf_document *xref, pdf_obj *rdb, pdf_obj *dict, fz_stream *c
{
/* Just load the compressed image data now and we can
* decode it on demand. */
- image->buffer = pdf_load_image_stream(xref, pdf_to_num(dict), pdf_to_gen(dict), &image->params);
+ int num = pdf_to_num(dict);
+ int gen = pdf_to_gen(dict);
+ image->buffer = pdf_load_image_stream(xref, num, gen, num, gen, &image->params);
break; /* Out of fz_try */
}
@@ -443,7 +448,7 @@ pdf_load_image_imp(pdf_document *xref, pdf_obj *rdb, pdf_obj *dict, fz_stream *c
/* RJW: "cannot open image data stream (%d 0 R)", pdf_to_num(dict) */
}
- image->tile = decomp_image_from_stream(ctx, stm, image, cstm != NULL, indexed, 1);
+ image->tile = decomp_image_from_stream(ctx, stm, image, cstm != NULL, indexed, 1, 0);
}
fz_catch(ctx)
{
diff --git a/pdf/pdf_interpret.c b/pdf/pdf_interpret.c
index a11b8c30..8851be6e 100644
--- a/pdf/pdf_interpret.c
+++ b/pdf/pdf_interpret.c
@@ -104,7 +104,7 @@ struct pdf_csi_s
fz_cookie *cookie;
};
-static void pdf_run_buffer(pdf_csi *csi, pdf_obj *rdb, fz_buffer *contents);
+static void pdf_run_contents_object(pdf_csi *csi, pdf_obj *rdb, pdf_obj *contents);
static void pdf_run_xobject(pdf_csi *csi, pdf_obj *resources, pdf_xobject *xobj, fz_matrix transform);
static void pdf_show_pattern(pdf_csi *csi, pdf_pattern *pat, fz_rect area, int what);
@@ -1291,7 +1291,7 @@ pdf_show_pattern(pdf_csi *csi, pdf_pattern *pat, fz_rect area, int what)
gstate->ctm = ptm;
csi->top_ctm = gstate->ctm;
pdf_gsave(csi);
- pdf_run_buffer(csi, pat->resources, pat->contents);
+ pdf_run_contents_object(csi, pat->resources, pat->contents);
/* RJW: "cannot render pattern tile" */
pdf_grestore(csi);
while (oldtop < csi->gtop)
@@ -1310,7 +1310,7 @@ pdf_show_pattern(pdf_csi *csi, pdf_pattern *pat, fz_rect area, int what)
pdf_gsave(csi);
fz_try(ctx)
{
- pdf_run_buffer(csi, pat->resources, pat->contents);
+ pdf_run_contents_object(csi, pat->resources, pat->contents);
}
fz_catch(ctx)
{
@@ -1407,7 +1407,7 @@ pdf_run_xobject(pdf_csi *csi, pdf_obj *resources, pdf_xobject *xobj, fz_matrix t
if (xobj->resources)
resources = xobj->resources;
- pdf_run_buffer(csi, resources, xobj->contents);
+ pdf_run_contents_object(csi, resources, xobj->contents);
/* RJW: "cannot interpret XObject stream" */
}
fz_always(ctx)
@@ -2528,7 +2528,6 @@ pdf_run_keyword(pdf_csi *csi, pdf_obj *rdb, fz_stream *file, char *buf)
fz_warn(ctx, "unknown keyword: '%s'", buf);
break;
}
- fz_assert_lock_not_held(ctx, FZ_LOCK_FILE);
}
static void
@@ -2662,44 +2661,78 @@ pdf_run_stream(pdf_csi *csi, pdf_obj *rdb, fz_stream *file, pdf_lexbuf *buf)
*/
static void
-pdf_run_buffer(pdf_csi *csi, pdf_obj *rdb, fz_buffer *contents)
+pdf_run_contents_stream(pdf_csi *csi, pdf_obj *rdb, fz_stream *file)
{
fz_context *ctx = csi->dev->ctx;
pdf_lexbuf_large *buf;
- fz_stream * file = NULL;
int save_in_text;
fz_var(buf);
- fz_var(file);
+
+ if (file == NULL)
+ return;
+
+ buf = fz_malloc(ctx, sizeof(*buf)); /* we must be re-entrant for type3 fonts */
+ buf->base.size = PDF_LEXBUF_LARGE;
+ save_in_text = csi->in_text;
+ csi->in_text = 0;
+ fz_try(ctx)
+ {
+ pdf_run_stream(csi, rdb, file, &buf->base);
+ }
+ fz_catch(ctx)
+ {
+ fz_warn(ctx, "Content stream parsing error - rendering truncated");
+ }
+ csi->in_text = save_in_text;
+ fz_free(ctx, buf);
+}
+
+static void
+pdf_run_contents_object(pdf_csi *csi, pdf_obj *rdb, pdf_obj *contents)
+{
+ fz_context *ctx = csi->dev->ctx;
+ fz_stream *file = NULL;
if (contents == NULL)
return;
+ file = pdf_open_contents_stream(csi->xref, contents);
fz_try(ctx)
{
- buf = fz_malloc(ctx, sizeof(*buf)); /* we must be re-entrant for type3 fonts */
- buf->base.size = PDF_LEXBUF_LARGE;
- file = fz_open_buffer(ctx, contents);
- save_in_text = csi->in_text;
- csi->in_text = 0;
- fz_try(ctx)
- {
- pdf_run_stream(csi, rdb, file, &buf->base);
- }
- fz_catch(ctx)
- {
- fz_warn(ctx, "Content stream parsing error - rendering truncated");
- }
- csi->in_text = save_in_text;
+ pdf_run_contents_stream(csi, rdb, file);
}
fz_always(ctx)
{
fz_close(file);
- fz_free(ctx, buf);
}
fz_catch(ctx)
{
- fz_throw(ctx, "cannot parse context stream");
+ fz_rethrow(ctx);
+ }
+}
+
+static void
+pdf_run_contents_buffer(pdf_csi *csi, pdf_obj *rdb, fz_buffer *contents)
+{
+ fz_context *ctx = csi->dev->ctx;
+ fz_stream *file = NULL;
+
+ if (contents == NULL)
+ return;
+
+ file = fz_open_buffer(ctx, contents);
+ fz_try(ctx)
+ {
+ pdf_run_contents_stream(csi, rdb, file);
+ }
+ fz_always(ctx)
+ {
+ fz_close(file);
+ }
+ fz_catch(ctx)
+ {
+ fz_rethrow(ctx);
}
}
@@ -2719,14 +2752,16 @@ pdf_run_page_with_usage(pdf_document *xref, pdf_page *page, fz_device *dev, fz_m
csi = pdf_new_csi(xref, dev, ctm, event, cookie, NULL);
fz_try(ctx)
{
- pdf_run_buffer(csi, page->resources, page->contents);
+ pdf_run_contents_object(csi, page->resources, page->contents);
}
- fz_catch(ctx)
+ fz_always(ctx)
{
pdf_free_csi(csi);
+ }
+ fz_catch(ctx)
+ {
fz_throw(ctx, "cannot parse page content stream");
}
- pdf_free_csi(csi);
if (cookie && cookie->progress_max != -1)
{
@@ -2792,7 +2827,7 @@ pdf_run_glyph(pdf_document *xref, pdf_obj *resources, fz_buffer *contents, fz_de
fz_try(ctx)
{
- pdf_run_buffer(csi, resources, contents);
+ pdf_run_contents_buffer(csi, resources, contents);
}
fz_catch(ctx)
{
diff --git a/pdf/pdf_js_none.c b/pdf/pdf_js_none.c
index a85103e4..bc8d2ee7 100644
--- a/pdf/pdf_js_none.c
+++ b/pdf/pdf_js_none.c
@@ -13,6 +13,10 @@ void pdf_drop_js(pdf_js *js)
{
}
+void pdf_js_setup_event(pdf_js *js, pdf_obj *target)
+{
+}
+
void pdf_js_execute(pdf_js *js, char *code)
{
}
diff --git a/pdf/base_object.c b/pdf/pdf_object.c
index 142bc128..3fb48019 100644
--- a/pdf/base_object.c
+++ b/pdf/pdf_object.c
@@ -145,8 +145,8 @@ pdf_new_indirect(fz_context *ctx, int num, int gen, void *xref)
pdf_obj *
pdf_keep_obj(pdf_obj *obj)
{
- assert(obj);
- obj->refs ++;
+ if (obj)
+ obj->refs ++;
return obj;
}
@@ -159,7 +159,6 @@ int pdf_is_indirect(pdf_obj *obj)
do { \
if (obj && obj->kind == PDF_INDIRECT) \
{\
- fz_assert_lock_not_held(obj->ctx, FZ_LOCK_FILE); \
obj = pdf_resolve_indirect(obj); \
} \
} while (0)
@@ -566,6 +565,8 @@ pdf_obj *pdf_new_rect(fz_context *ctx, fz_rect *rect)
pdf_obj *arr = NULL;
pdf_obj *item = NULL;
+ fz_var(arr);
+ fz_var(item);
fz_try(ctx)
{
arr = pdf_new_array(ctx, 4);
@@ -605,6 +606,8 @@ pdf_obj *pdf_new_matrix(fz_context *ctx, fz_matrix *mtx)
pdf_obj *arr = NULL;
pdf_obj *item = NULL;
+ fz_var(arr);
+ fz_var(item);
fz_try(ctx)
{
arr = pdf_new_array(ctx, 6);
diff --git a/pdf/pdf_page.c b/pdf/pdf_page.c
index 3e95e9a5..39554551 100644
--- a/pdf/pdf_page.c
+++ b/pdf/pdf_page.c
@@ -114,6 +114,8 @@ pdf_load_page_tree_node(pdf_document *xref, pdf_obj *node, struct info info)
}
}
/* Get the next node */
+ if (stacklen < 0)
+ break;
while (++stack[stacklen].pos == stack[stacklen].max)
{
pdf_dict_unmark(stack[stacklen].node);
@@ -279,72 +281,6 @@ found:
return useBM;
}
-/* we need to combine all sub-streams into one for the content stream interpreter */
-
-static fz_buffer *
-pdf_load_page_contents_array(pdf_document *xref, pdf_obj *list)
-{
- fz_buffer *big;
- fz_buffer *one;
- int i, n;
- fz_context *ctx = xref->ctx;
-
- big = fz_new_buffer(ctx, 32 * 1024);
-
- n = pdf_array_len(list);
- fz_var(i); /* Workaround Mac compiler bug */
- for (i = 0; i < n; i++)
- {
- pdf_obj *stm = pdf_array_get(list, i);
- fz_try(ctx)
- {
- one = pdf_load_stream(xref, pdf_to_num(stm), pdf_to_gen(stm));
- }
- fz_catch(ctx)
- {
- fz_warn(ctx, "cannot load content stream part %d/%d", i + 1, n);
- continue;
- }
-
- if (big->len + one->len + 1 > big->cap)
- fz_resize_buffer(ctx, big, big->len + one->len + 1);
- memcpy(big->data + big->len, one->data, one->len);
- big->data[big->len + one->len] = ' ';
- big->len += one->len + 1;
-
- fz_drop_buffer(ctx, one);
- }
-
- if (n > 0 && big->len == 0)
- {
- fz_drop_buffer(ctx, big);
- fz_throw(ctx, "cannot load content stream");
- }
- fz_trim_buffer(ctx, big);
-
- return big;
-}
-
-static fz_buffer *
-pdf_load_page_contents(pdf_document *xref, pdf_obj *obj)
-{
- fz_context *ctx = xref->ctx;
-
- if (pdf_is_array(obj))
- {
- return pdf_load_page_contents_array(xref, obj);
- /* RJW: "cannot load content stream array" */
- }
- else if (pdf_is_stream(xref, pdf_to_num(obj), pdf_to_gen(obj)))
- {
- return pdf_load_stream(xref, pdf_to_num(obj), pdf_to_gen(obj));
- /* RJW: "cannot load content stream (%d 0 R)", pdf_to_num(obj) */
- }
-
- fz_warn(ctx, "page contents missing, leaving page blank");
- return fz_new_buffer(ctx, 0);
-}
-
pdf_page *
pdf_load_page(pdf_document *xref, int number)
{
@@ -422,7 +358,7 @@ pdf_load_page(pdf_document *xref, int number)
obj = pdf_dict_gets(pageobj, "Contents");
fz_try(ctx)
{
- page->contents = pdf_load_page_contents(xref, obj);
+ page->contents = pdf_keep_obj(obj);
if (pdf_resources_use_blending(ctx, page->resources))
page->transparency = 1;
@@ -462,7 +398,7 @@ pdf_free_page(pdf_document *xref, pdf_page *page)
if (page->resources)
pdf_drop_obj(page->resources);
if (page->contents)
- fz_drop_buffer(xref->ctx, page->contents);
+ pdf_drop_obj(page->contents);
if (page->links)
fz_drop_link(xref->ctx, page->links);
if (page->annots)
diff --git a/pdf/pdf_parse.c b/pdf/pdf_parse.c
index fe9db368..b1472d1a 100644
--- a/pdf/pdf_parse.c
+++ b/pdf/pdf_parse.c
@@ -453,21 +453,19 @@ pdf_parse_ind_obj(pdf_document *xref,
fz_var(obj);
tok = pdf_lex(file, buf);
- /* RJW: cannot parse indirect object (%d %d R)", num, gen */
if (tok != PDF_TOK_INT)
- fz_throw(ctx, "expected object number (%d %d R)", num, gen);
+ fz_throw(ctx, "expected object number");
num = buf->i;
tok = pdf_lex(file, buf);
- /* RJW: "cannot parse indirect object (%d %d R)", num, gen */
if (tok != PDF_TOK_INT)
- fz_throw(ctx, "expected generation number (%d %d R)", num, gen);
+ fz_throw(ctx, "expected generation number (%d ? obj)", num);
gen = buf->i;
tok = pdf_lex(file, buf);
/* RJW: "cannot parse indirect object (%d %d R)", num, gen */
if (tok != PDF_TOK_OBJ)
- fz_throw(ctx, "expected 'obj' keyword (%d %d R)", num, gen);
+ fz_throw(ctx, "expected 'obj' keyword (%d %d ?)", num, gen);
tok = pdf_lex(file, buf);
/* RJW: "cannot parse indirect object (%d %d R)", num, gen */
diff --git a/pdf/pdf_pattern.c b/pdf/pdf_pattern.c
index 14175670..af96c2d5 100644
--- a/pdf/pdf_pattern.c
+++ b/pdf/pdf_pattern.c
@@ -21,7 +21,7 @@ pdf_free_pattern_imp(fz_context *ctx, fz_storable *pat_)
if (pat->resources)
pdf_drop_obj(pat->resources);
if (pat->contents)
- fz_drop_buffer(ctx, pat->contents);
+ pdf_drop_obj(pat->contents);
fz_free(ctx, pat);
}
@@ -30,7 +30,7 @@ pdf_pattern_size(pdf_pattern *pat)
{
if (pat == NULL)
return 0;
- return sizeof(*pat) + (pat->contents ? pat->contents->cap : 0);
+ return sizeof(*pat);
}
pdf_pattern *
@@ -72,7 +72,7 @@ pdf_load_pattern(pdf_document *xref, pdf_obj *dict)
fz_try(ctx)
{
- pat->contents = pdf_load_stream(xref, pdf_to_num(dict), pdf_to_gen(dict));
+ pat->contents = pdf_keep_obj(dict);
}
fz_catch(ctx)
{
diff --git a/pdf/pdf_repair.c b/pdf/pdf_repair.c
index a51b9631..27846855 100644
--- a/pdf/pdf_repair.c
+++ b/pdf/pdf_repair.c
@@ -195,6 +195,7 @@ pdf_repair_obj_stm(pdf_document *xref, int num, int gen)
}
}
+/* Entered with file locked, remains locked throughout. */
void
pdf_repair_xref(pdf_document *xref, pdf_lexbuf *buf)
{
@@ -389,19 +390,7 @@ pdf_repair_xref(pdf_document *xref, pdf_lexbuf *buf)
/* corrected stream length */
if (list[i].stm_len >= 0)
{
- fz_unlock(ctx, FZ_LOCK_FILE);
- fz_try(ctx)
- {
- dict = pdf_load_object(xref, list[i].num, list[i].gen);
- }
- fz_always(ctx)
- {
- fz_lock(ctx, FZ_LOCK_FILE);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
+ dict = pdf_load_object(xref, list[i].num, list[i].gen);
/* RJW: "cannot load stream object (%d %d R)", list[i].num, list[i].gen */
length = pdf_new_int(ctx, list[i].stm_len);
diff --git a/pdf/pdf_stream.c b/pdf/pdf_stream.c
index 84f966ec..89d94004 100644
--- a/pdf/pdf_stream.c
+++ b/pdf/pdf_stream.c
@@ -13,7 +13,7 @@ pdf_is_stream(pdf_document *xref, int num, int gen)
pdf_cache_object(xref, num, gen);
/* RJW: "cannot load object, ignoring error" */
- return xref->table[num].stm_ofs > 0;
+ return xref->table[num].stm_ofs > 0 || xref->table[num].stm_buf;
}
/*
@@ -222,21 +222,27 @@ build_filter_chain(fz_stream *chain, pdf_document *xref, pdf_obj *fs, pdf_obj *p
/*
* Build a filter for reading raw stream data.
- * This is a null filter to constrain reading to the
- * stream length, followed by a decryption filter.
+ * This is a null filter to constrain reading to the stream length (and to
+ * allow for other people accessing the file), followed by a decryption
+ * filter.
+ *
+ * num and gen are used purely to seed the encryption.
*/
static fz_stream *
-pdf_open_raw_filter(fz_stream *chain, pdf_document *xref, pdf_obj *stmobj, int num, int gen)
+pdf_open_raw_filter(fz_stream *chain, pdf_document *xref, pdf_obj *stmobj, int num, int gen, int offset)
{
+ fz_context *ctx = chain->ctx;
int hascrypt;
int len;
- fz_context *ctx = chain->ctx;
+
+ if (num > 0 && num < xref->len && xref->table[num].stm_buf)
+ return fz_open_buffer(ctx, xref->table[num].stm_buf);
/* don't close chain when we close this filter */
fz_keep_stream(chain);
len = pdf_to_int(pdf_dict_gets(stmobj, "Length"));
- chain = fz_open_null(chain, len);
+ chain = fz_open_null(chain, len, offset);
fz_try(ctx)
{
@@ -258,7 +264,7 @@ pdf_open_raw_filter(fz_stream *chain, pdf_document *xref, pdf_obj *stmobj, int n
* to stream length and decrypting.
*/
static fz_stream *
-pdf_open_filter(fz_stream *chain, pdf_document *xref, pdf_obj *stmobj, int num, int gen, pdf_image_params *imparams)
+pdf_open_filter(fz_stream *chain, pdf_document *xref, pdf_obj *stmobj, int num, int gen, int offset, pdf_image_params *imparams)
{
pdf_obj *filters;
pdf_obj *params;
@@ -266,14 +272,13 @@ pdf_open_filter(fz_stream *chain, pdf_document *xref, pdf_obj *stmobj, int num,
filters = pdf_dict_getsa(stmobj, "Filter", "F");
params = pdf_dict_getsa(stmobj, "DecodeParms", "DP");
- chain = pdf_open_raw_filter(chain, xref, stmobj, num, gen);
+ chain = pdf_open_raw_filter(chain, xref, stmobj, num, gen, offset);
if (pdf_is_name(filters))
chain = build_filter(chain, xref, filters, params, num, gen, imparams);
else if (pdf_array_len(filters) > 0)
chain = build_filter_chain(chain, xref, filters, params, num, gen, imparams);
- fz_lock_stream(chain);
return chain;
}
@@ -298,20 +303,22 @@ pdf_open_inline_stream(pdf_document *xref, pdf_obj *stmobj, int length, fz_strea
if (pdf_array_len(filters) > 0)
return build_filter_chain(chain, xref, filters, params, 0, 0, imparams);
- return fz_open_null(chain, length);
+ return fz_open_null(chain, length, fz_tell(chain));
}
/*
* Open a stream for reading the raw (compressed but decrypted) data.
- * Using xref->file while this is open is a bad idea.
*/
fz_stream *
pdf_open_raw_stream(pdf_document *xref, int num, int gen)
{
- pdf_xref_entry *x;
- fz_stream *stm;
+ return pdf_open_raw_renumbered_stream(xref, num, gen, num, gen);
+}
- fz_var(x);
+fz_stream *
+pdf_open_raw_renumbered_stream(pdf_document *xref, int num, int gen, int orig_num, int orig_gen)
+{
+ pdf_xref_entry *x;
if (num < 0 || num >= xref->len)
fz_throw(xref->ctx, "object id out of range (%d %d R)", num, gen);
@@ -324,10 +331,7 @@ pdf_open_raw_stream(pdf_document *xref, int num, int gen)
if (x->stm_ofs == 0)
fz_throw(xref->ctx, "object is not a stream");
- stm = pdf_open_raw_filter(xref->file, xref, x->obj, num, gen);
- fz_lock_stream(stm);
- fz_seek(xref->file, x->stm_ofs, 0);
- return stm;
+ return pdf_open_raw_filter(xref->file, xref, x->obj, orig_num, orig_gen, x->stm_ofs);
}
/*
@@ -338,14 +342,13 @@ pdf_open_raw_stream(pdf_document *xref, int num, int gen)
fz_stream *
pdf_open_stream(pdf_document *xref, int num, int gen)
{
- return pdf_open_image_stream(xref, num, gen, NULL);
+ return pdf_open_image_stream(xref, num, gen, num, gen, NULL);
}
fz_stream *
-pdf_open_image_stream(pdf_document *xref, int num, int gen, pdf_image_params *params)
+pdf_open_image_stream(pdf_document *xref, int num, int gen, int orig_num, int orig_gen, pdf_image_params *params)
{
pdf_xref_entry *x;
- fz_stream *stm;
if (num < 0 || num >= xref->len)
fz_throw(xref->ctx, "object id out of range (%d %d R)", num, gen);
@@ -355,12 +358,10 @@ pdf_open_image_stream(pdf_document *xref, int num, int gen, pdf_image_params *pa
pdf_cache_object(xref, num, gen);
/* RJW: "cannot load stream object (%d %d R)", num, gen */
- if (x->stm_ofs == 0)
+ if (x->stm_ofs == 0 && x->stm_buf == NULL)
fz_throw(xref->ctx, "object is not a stream");
- stm = pdf_open_filter(xref->file, xref, x->obj, num, gen, params);
- fz_seek(xref->file, x->stm_ofs, 0);
- return stm;
+ return pdf_open_filter(xref->file, xref, x->obj, orig_num, orig_gen, x->stm_ofs, params);
}
fz_stream *
@@ -410,14 +411,10 @@ pdf_open_image_decomp_stream(fz_context *ctx, fz_buffer *buffer, pdf_image_param
fz_stream *
pdf_open_stream_with_offset(pdf_document *xref, int num, int gen, pdf_obj *dict, int stm_ofs)
{
- fz_stream *stm;
-
if (stm_ofs == 0)
fz_throw(xref->ctx, "object is not a stream");
- stm = pdf_open_filter(xref->file, xref, dict, num, gen, NULL);
- fz_seek(xref->file, stm_ofs, 0);
- return stm;
+ return pdf_open_filter(xref->file, xref, dict, num, gen, stm_ofs, NULL);
}
/*
@@ -426,11 +423,20 @@ pdf_open_stream_with_offset(pdf_document *xref, int num, int gen, pdf_obj *dict,
fz_buffer *
pdf_load_raw_stream(pdf_document *xref, int num, int gen)
{
+ return pdf_load_raw_renumbered_stream(xref, num, gen, num, gen);
+}
+
+fz_buffer *
+pdf_load_raw_renumbered_stream(pdf_document *xref, int num, int gen, int orig_num, int orig_gen)
+{
fz_stream *stm;
pdf_obj *dict;
int len;
fz_buffer *buf;
+ if (num > 0 && num < xref->len && xref->table[num].stm_buf)
+ return fz_keep_buffer(xref->ctx, xref->table[num].stm_buf);
+
dict = pdf_load_object(xref, num, gen);
/* RJW: "cannot load stream dictionary (%d %d R)", num, gen */
@@ -438,7 +444,7 @@ pdf_load_raw_stream(pdf_document *xref, int num, int gen)
pdf_drop_obj(dict);
- stm = pdf_open_raw_stream(xref, num, gen);
+ stm = pdf_open_raw_renumbered_stream(xref, num, gen, orig_num, orig_gen);
/* RJW: "cannot open raw stream (%d %d R)", num, gen */
buf = fz_read_all(stm, len);
@@ -470,11 +476,17 @@ pdf_guess_filter_length(int len, char *filter)
fz_buffer *
pdf_load_stream(pdf_document *xref, int num, int gen)
{
- return pdf_load_image_stream(xref, num, gen, NULL);
+ return pdf_load_image_stream(xref, num, gen, num, gen, NULL);
+}
+
+fz_buffer *
+pdf_load_renumbered_stream(pdf_document *xref, int num, int gen, int orig_num, int orig_gen)
+{
+ return pdf_load_image_stream(xref, num, gen, orig_num, orig_gen, NULL);
}
fz_buffer *
-pdf_load_image_stream(pdf_document *xref, int num, int gen, pdf_image_params *params)
+pdf_load_image_stream(pdf_document *xref, int num, int gen, int orig_num, int orig_gen, pdf_image_params *params)
{
fz_context *ctx = xref->ctx;
fz_stream *stm = NULL;
@@ -496,7 +508,7 @@ pdf_load_image_stream(pdf_document *xref, int num, int gen, pdf_image_params *pa
pdf_drop_obj(dict);
- stm = pdf_open_image_stream(xref, num, gen, params);
+ stm = pdf_open_image_stream(xref, num, gen, orig_num, orig_gen, params);
/* RJW: "cannot open stream (%d %d R)", num, gen */
fz_try(ctx)
@@ -514,3 +526,49 @@ pdf_load_image_stream(pdf_document *xref, int num, int gen, pdf_image_params *pa
return buf;
}
+
+static fz_stream *
+pdf_open_object_array(pdf_document *xref, pdf_obj *list)
+{
+ int i, n;
+ fz_context *ctx = xref->ctx;
+ fz_stream *stm;
+
+ n = pdf_array_len(list);
+ stm = fz_open_concat(ctx, n, 1);
+
+ fz_var(i); /* Workaround Mac compiler bug */
+ for (i = 0; i < n; i++)
+ {
+ pdf_obj *obj = pdf_array_get(list, i);
+ fz_try(ctx)
+ {
+ fz_concat_push(stm, pdf_open_stream(xref, pdf_to_num(obj), pdf_to_gen(obj)));
+ }
+ fz_catch(ctx)
+ {
+ fz_warn(ctx, "cannot load content stream part %d/%d", i + 1, n);
+ continue;
+ }
+ }
+
+ return stm;
+}
+
+fz_stream *
+pdf_open_contents_stream(pdf_document *xref, pdf_obj *obj)
+{
+ fz_context *ctx = xref->ctx;
+ int num, gen;
+
+ if (pdf_is_array(obj))
+ return pdf_open_object_array(xref, obj);
+
+ num = pdf_to_num(obj);
+ gen = pdf_to_gen(obj);
+ if (pdf_is_stream(xref, num, gen))
+ return pdf_open_image_stream(xref, num, gen, num, gen, NULL);
+
+ fz_warn(ctx, "pdf object stream missing (%d %d R)", num, gen);
+ return NULL;
+}
diff --git a/pdf/pdf_type3.c b/pdf/pdf_type3.c
index 6603fc8b..4df46ce3 100644
--- a/pdf/pdf_type3.c
+++ b/pdf/pdf_type3.c
@@ -2,10 +2,9 @@
#include "mupdf-internal.h"
static void
-pdf_run_glyph_func(void *doc, void *rdb_, fz_buffer *contents, fz_device *dev, fz_matrix ctm, void *gstate)
+pdf_run_glyph_func(void *doc, void *rdb, fz_buffer *contents, fz_device *dev, fz_matrix ctm, void *gstate)
{
- pdf_obj *rdb = (pdf_obj *)rdb_;
- pdf_run_glyph(doc, rdb, contents, dev, ctm, gstate);
+ pdf_run_glyph(doc, (pdf_obj *)rdb, contents, dev, ctm, gstate);
}
static void
diff --git a/pdf/pdf_write.c b/pdf/pdf_write.c
new file mode 100644
index 00000000..ed0b8711
--- /dev/null
+++ b/pdf/pdf_write.c
@@ -0,0 +1,690 @@
+#include "fitz.h"
+#include "mupdf-internal.h"
+
+typedef struct pdf_write_options_s pdf_write_options;
+
+struct pdf_write_options_s
+{
+ FILE *out;
+ int doascii;
+ int doexpand;
+ int dogarbage;
+ char *uselist;
+ int *ofslist;
+ int *genlist;
+ int *renumbermap;
+ int *revrenumbermap;
+ int *revgenlist;
+};
+
+/*
+ * Garbage collect objects not reachable from the trailer.
+ */
+
+static pdf_obj *sweepref(pdf_document *xref, pdf_write_options *opts, pdf_obj *obj)
+{
+ int num = pdf_to_num(obj);
+ int gen = pdf_to_gen(obj);
+ fz_context *ctx = xref->ctx;
+
+ if (num < 0 || num >= xref->len)
+ return NULL;
+ if (opts->uselist[num])
+ return NULL;
+
+ opts->uselist[num] = 1;
+
+ /* Bake in /Length in stream objects */
+ fz_try(ctx)
+ {
+ if (pdf_is_stream(xref, num, gen))
+ {
+ pdf_obj *len = pdf_dict_gets(obj, "Length");
+ if (pdf_is_indirect(len))
+ {
+ opts->uselist[pdf_to_num(len)] = 0;
+ len = pdf_resolve_indirect(len);
+ pdf_dict_puts(obj, "Length", len);
+ }
+ }
+ }
+ fz_catch(ctx)
+ {
+ /* Leave broken */
+ }
+
+ return pdf_resolve_indirect(obj);
+}
+
+static void sweepobj(pdf_document *xref, pdf_write_options *opts, pdf_obj *obj)
+{
+ int i;
+
+ if (pdf_is_indirect(obj))
+ obj = sweepref(xref, opts, obj);
+
+ if (pdf_is_dict(obj))
+ {
+ int n = pdf_dict_len(obj);
+ for (i = 0; i < n; i++)
+ sweepobj(xref, opts, pdf_dict_get_val(obj, i));
+ }
+
+ else if (pdf_is_array(obj))
+ {
+ int n = pdf_array_len(obj);
+ for (i = 0; i < n; i++)
+ sweepobj(xref, opts, pdf_array_get(obj, i));
+ }
+}
+
+/*
+ * Scan for and remove duplicate objects (slow)
+ */
+
+static void removeduplicateobjs(pdf_document *xref, pdf_write_options *opts)
+{
+ int num, other;
+ fz_context *ctx = xref->ctx;
+
+ for (num = 1; num < xref->len; num++)
+ {
+ /* Only compare an object to objects preceding it */
+ for (other = 1; other < num; other++)
+ {
+ pdf_obj *a, *b;
+ int differ, newnum;
+
+ if (num == other || !opts->uselist[num] || !opts->uselist[other])
+ continue;
+
+ /*
+ * Comparing stream objects data contents would take too long.
+ *
+ * pdf_is_stream calls pdf_cache_object and ensures
+ * that the xref table has the objects loaded.
+ */
+ fz_try(ctx)
+ {
+ differ = (pdf_is_stream(xref, num, 0) || pdf_is_stream(xref, other, 0));
+ }
+ fz_catch(ctx)
+ {
+ /* Assume different */
+ differ = 1;
+ }
+ if (differ)
+ continue;
+
+ a = xref->table[num].obj;
+ b = xref->table[other].obj;
+
+ a = pdf_resolve_indirect(a);
+ b = pdf_resolve_indirect(b);
+
+ if (pdf_objcmp(a, b))
+ continue;
+
+ /* Keep the lowest numbered object */
+ newnum = MIN(num, other);
+ opts->renumbermap[num] = newnum;
+ opts->renumbermap[other] = newnum;
+ opts->revrenumbermap[newnum] = num; /* Either will do */
+ opts->uselist[MAX(num, other)] = 0;
+
+ /* One duplicate was found, do not look for another */
+ break;
+ }
+ }
+}
+
+/*
+ * Renumber objects sequentially so the xref is more compact
+ *
+ * This code assumes that any opts->renumbermap[n] <= n for all n.
+ */
+
+static void compactxref(pdf_document *xref, pdf_write_options *opts)
+{
+ int num, newnum;
+
+ /*
+ * Update renumbermap in-place, clustering all used
+ * objects together at low object ids. Objects that
+ * already should be renumbered will have their new
+ * object ids be updated to reflect the compaction.
+ */
+
+ newnum = 1;
+ for (num = 1; num < xref->len; num++)
+ {
+ /* If it's not used, map it to zero */
+ if (!opts->uselist[num])
+ {
+ opts->renumbermap[num] = 0;
+ }
+ /* If it's not moved, compact it. */
+ else if (opts->renumbermap[num] == num)
+ {
+ opts->revrenumbermap[newnum] = opts->revrenumbermap[num];
+ opts->revgenlist[newnum] = opts->revgenlist[num];
+ opts->renumbermap[num] = newnum++;
+ }
+ /* Otherwise it's used, and moved. We know that it must have
+ * moved down, so the place it's moved to will be in the right
+ * place already. */
+ else
+ {
+ opts->renumbermap[num] = opts->renumbermap[opts->renumbermap[num]];
+ }
+ }
+}
+
+/*
+ * Update indirect objects according to renumbering established when
+ * removing duplicate objects and compacting the xref.
+ */
+
+static void renumberobj(pdf_document *xref, pdf_write_options *opts, pdf_obj *obj)
+{
+ int i;
+ fz_context *ctx = xref->ctx;
+
+ if (pdf_is_dict(obj))
+ {
+ int n = pdf_dict_len(obj);
+ for (i = 0; i < n; i++)
+ {
+ pdf_obj *key = pdf_dict_get_key(obj, i);
+ pdf_obj *val = pdf_dict_get_val(obj, i);
+ if (pdf_is_indirect(val))
+ {
+ val = pdf_new_indirect(ctx, opts->renumbermap[pdf_to_num(val)], 0, xref);
+ fz_dict_put(obj, key, val);
+ pdf_drop_obj(val);
+ }
+ else
+ {
+ renumberobj(xref, opts, val);
+ }
+ }
+ }
+
+ else if (pdf_is_array(obj))
+ {
+ int n = pdf_array_len(obj);
+ for (i = 0; i < n; i++)
+ {
+ pdf_obj *val = pdf_array_get(obj, i);
+ if (pdf_is_indirect(val))
+ {
+ val = pdf_new_indirect(ctx, opts->renumbermap[pdf_to_num(val)], 0, xref);
+ pdf_array_put(obj, i, val);
+ pdf_drop_obj(val);
+ }
+ else
+ {
+ renumberobj(xref, opts, val);
+ }
+ }
+ }
+}
+
+static void renumberobjs(pdf_document *xref, pdf_write_options *opts)
+{
+ pdf_xref_entry *oldxref;
+ int newlen;
+ int num;
+ fz_context *ctx = xref->ctx;
+
+ /* Apply renumber map to indirect references in all objects in xref */
+ renumberobj(xref, opts, xref->trailer);
+ for (num = 0; num < xref->len; num++)
+ {
+ pdf_obj *obj = xref->table[num].obj;
+
+ if (pdf_is_indirect(obj))
+ {
+ obj = pdf_new_indirect(ctx, opts->renumbermap[pdf_to_num(obj)], 0, xref);
+ pdf_update_object(xref, num, obj);
+ pdf_drop_obj(obj);
+ }
+ else
+ {
+ renumberobj(xref, opts, obj);
+ }
+ }
+
+ /* Create new table for the reordered, compacted xref */
+ oldxref = xref->table;
+ xref->table = fz_malloc_array(xref->ctx, xref->len, sizeof(pdf_xref_entry));
+ xref->table[0] = oldxref[0];
+
+ /* Move used objects into the new compacted xref */
+ newlen = 0;
+ for (num = 1; num < xref->len; num++)
+ {
+ if (opts->uselist[num])
+ {
+ if (newlen < opts->renumbermap[num])
+ newlen = opts->renumbermap[num];
+ xref->table[opts->renumbermap[num]] = oldxref[num];
+ }
+ else
+ {
+ if (oldxref[num].obj)
+ pdf_drop_obj(oldxref[num].obj);
+ }
+ }
+
+ fz_free(xref->ctx, oldxref);
+
+ /* Update the used objects count in compacted xref */
+ xref->len = newlen + 1;
+
+ /* Update list of used objects to fit with compacted xref */
+ for (num = 1; num < xref->len; num++)
+ opts->uselist[num] = 1;
+}
+
+/*
+ * Make sure we have loaded objects from object streams.
+ */
+
+static void preloadobjstms(pdf_document *xref)
+{
+ pdf_obj *obj;
+ int num;
+
+ for (num = 0; num < xref->len; num++)
+ {
+ if (xref->table[num].type == 'o')
+ {
+ obj = pdf_load_object(xref, num, 0);
+ pdf_drop_obj(obj);
+ }
+ }
+}
+
+/*
+ * Save streams and objects to the output
+ */
+
+static inline int isbinary(int c)
+{
+ if (c == '\n' || c == '\r' || c == '\t')
+ return 0;
+ return c < 32 || c > 127;
+}
+
+static int isbinarystream(fz_buffer *buf)
+{
+ int i;
+ for (i = 0; i < buf->len; i++)
+ if (isbinary(buf->data[i]))
+ return 1;
+ return 0;
+}
+
+static fz_buffer *hexbuf(fz_context *ctx, unsigned char *p, int n)
+{
+ static const char hex[16] = "0123456789abcdef";
+ fz_buffer *buf;
+ int x = 0;
+
+ buf = fz_new_buffer(ctx, n * 2 + (n / 32) + 2);
+
+ while (n--)
+ {
+ buf->data[buf->len++] = hex[*p >> 4];
+ buf->data[buf->len++] = hex[*p & 15];
+ if (++x == 32)
+ {
+ buf->data[buf->len++] = '\n';
+ x = 0;
+ }
+ p++;
+ }
+
+ buf->data[buf->len++] = '>';
+ buf->data[buf->len++] = '\n';
+
+ return buf;
+}
+
+static void addhexfilter(pdf_document *xref, pdf_obj *dict)
+{
+ pdf_obj *f, *dp, *newf, *newdp;
+ pdf_obj *ahx, *nullobj;
+ fz_context *ctx = xref->ctx;
+
+ ahx = fz_new_name(ctx, "ASCIIHexDecode");
+ nullobj = pdf_new_null(ctx);
+ newf = newdp = NULL;
+
+ f = pdf_dict_gets(dict, "Filter");
+ dp = pdf_dict_gets(dict, "DecodeParms");
+
+ if (pdf_is_name(f))
+ {
+ newf = pdf_new_array(ctx, 2);
+ pdf_array_push(newf, ahx);
+ pdf_array_push(newf, f);
+ f = newf;
+ if (pdf_is_dict(dp))
+ {
+ newdp = pdf_new_array(ctx, 2);
+ pdf_array_push(newdp, nullobj);
+ pdf_array_push(newdp, dp);
+ dp = newdp;
+ }
+ }
+ else if (pdf_is_array(f))
+ {
+ pdf_array_insert(f, ahx);
+ if (pdf_is_array(dp))
+ pdf_array_insert(dp, nullobj);
+ }
+ else
+ f = ahx;
+
+ pdf_dict_puts(dict, "Filter", f);
+ if (dp)
+ pdf_dict_puts(dict, "DecodeParms", dp);
+
+ pdf_drop_obj(ahx);
+ pdf_drop_obj(nullobj);
+ if (newf)
+ pdf_drop_obj(newf);
+ if (newdp)
+ pdf_drop_obj(newdp);
+}
+
+static void copystream(pdf_document *xref, pdf_write_options *opts, pdf_obj *obj, int num, int gen)
+{
+ fz_buffer *buf, *tmp;
+ pdf_obj *newlen;
+ fz_context *ctx = xref->ctx;
+ int orig_num = opts->revrenumbermap[num];
+ int orig_gen = opts->revgenlist[num];
+
+ buf = pdf_load_raw_renumbered_stream(xref, num, gen, orig_num, orig_gen);
+
+ if (opts->doascii && isbinarystream(buf))
+ {
+ tmp = hexbuf(ctx, buf->data, buf->len);
+ fz_drop_buffer(ctx, buf);
+ buf = tmp;
+
+ addhexfilter(xref, obj);
+
+ newlen = pdf_new_int(ctx, buf->len);
+ pdf_dict_puts(obj, "Length", newlen);
+ pdf_drop_obj(newlen);
+ }
+
+ fprintf(opts->out, "%d %d obj\n", num, gen);
+ pdf_fprint_obj(opts->out, obj, opts->doexpand == 0);
+ fprintf(opts->out, "stream\n");
+ fwrite(buf->data, 1, buf->len, opts->out);
+ fprintf(opts->out, "endstream\nendobj\n\n");
+
+ fz_drop_buffer(ctx, buf);
+}
+
+static void expandstream(pdf_document *xref, pdf_write_options *opts, pdf_obj *obj, int num, int gen)
+{
+ fz_buffer *buf, *tmp;
+ pdf_obj *newlen;
+ fz_context *ctx = xref->ctx;
+ int orig_num = opts->revrenumbermap[num];
+ int orig_gen = opts->revgenlist[num];
+
+ buf = pdf_load_renumbered_stream(xref, num, gen, orig_num, orig_gen);
+
+ pdf_dict_dels(obj, "Filter");
+ pdf_dict_dels(obj, "DecodeParms");
+
+ if (opts->doascii && isbinarystream(buf))
+ {
+ tmp = hexbuf(ctx, buf->data, buf->len);
+ fz_drop_buffer(ctx, buf);
+ buf = tmp;
+
+ addhexfilter(xref, obj);
+ }
+
+ newlen = pdf_new_int(ctx, buf->len);
+ pdf_dict_puts(obj, "Length", newlen);
+ pdf_drop_obj(newlen);
+
+ fprintf(opts->out, "%d %d obj\n", num, gen);
+ pdf_fprint_obj(opts->out, obj, opts->doexpand == 0);
+ fprintf(opts->out, "stream\n");
+ fwrite(buf->data, 1, buf->len, opts->out);
+ fprintf(opts->out, "endstream\nendobj\n\n");
+
+ fz_drop_buffer(ctx, buf);
+}
+
+static void writeobject(pdf_document *xref, pdf_write_options *opts, int num, int gen)
+{
+ pdf_obj *obj;
+ pdf_obj *type;
+ fz_context *ctx = xref->ctx;
+
+ obj = pdf_load_object(xref, num, gen);
+
+ /* skip ObjStm and XRef objects */
+ if (pdf_is_dict(obj))
+ {
+ type = pdf_dict_gets(obj, "Type");
+ if (pdf_is_name(type) && !strcmp(pdf_to_name(type), "ObjStm"))
+ {
+ opts->uselist[num] = 0;
+ pdf_drop_obj(obj);
+ return;
+ }
+ if (pdf_is_name(type) && !strcmp(pdf_to_name(type), "XRef"))
+ {
+ opts->uselist[num] = 0;
+ pdf_drop_obj(obj);
+ return;
+ }
+ }
+
+ if (!pdf_is_stream(xref, num, gen))
+ {
+ fprintf(opts->out, "%d %d obj\n", num, gen);
+ pdf_fprint_obj(opts->out, obj, opts->doexpand == 0);
+ fprintf(opts->out, "endobj\n\n");
+ }
+ else
+ {
+ int dontexpand = 0;
+ if (opts->doexpand != 0 && opts->doexpand != fz_expand_all)
+ {
+ pdf_obj *o;
+
+ if ((o = pdf_dict_gets(obj, "Type"), !strcmp(pdf_to_name(o), "XObject")) &&
+ (o = pdf_dict_gets(obj, "Subtype"), !strcmp(pdf_to_name(o), "Image")))
+ dontexpand = !(opts->doexpand & fz_expand_images);
+ if (o = pdf_dict_gets(obj, "Type"), !strcmp(pdf_to_name(o), "Font"))
+ dontexpand = !(opts->doexpand & fz_expand_fonts);
+ if (o = pdf_dict_gets(obj, "Type"), !strcmp(pdf_to_name(o), "FontDescriptor"))
+ dontexpand = !(opts->doexpand & fz_expand_fonts);
+ if ((o = pdf_dict_gets(obj, "Length1")) != NULL)
+ dontexpand = !(opts->doexpand & fz_expand_fonts);
+ if ((o = pdf_dict_gets(obj, "Length2")) != NULL)
+ dontexpand = !(opts->doexpand & fz_expand_fonts);
+ if ((o = pdf_dict_gets(obj, "Length3")) != NULL)
+ dontexpand = !(opts->doexpand & fz_expand_fonts);
+ if (o = pdf_dict_gets(obj, "Subtype"), !strcmp(pdf_to_name(o), "Type1C"))
+ dontexpand = !(opts->doexpand & fz_expand_fonts);
+ if (o = pdf_dict_gets(obj, "Subtype"), !strcmp(pdf_to_name(o), "CIDFontType0C"))
+ dontexpand = !(opts->doexpand & fz_expand_fonts);
+ }
+ if (opts->doexpand && !dontexpand && !pdf_is_jpx_image(ctx, obj))
+ expandstream(xref, opts, obj, num, gen);
+ else
+ copystream(xref, opts, obj, num, gen);
+ }
+
+ pdf_drop_obj(obj);
+}
+
+static void writexref(pdf_document *xref, pdf_write_options *opts)
+{
+ pdf_obj *trailer;
+ pdf_obj *obj;
+ int startxref;
+ int num;
+ fz_context *ctx = xref->ctx;
+
+ startxref = ftell(opts->out);
+
+ fprintf(opts->out, "xref\n0 %d\n", xref->len);
+ for (num = 0; num < xref->len; num++)
+ {
+ if (opts->uselist[num])
+ fprintf(opts->out, "%010d %05d n \n", opts->ofslist[num], opts->genlist[num]);
+ else
+ fprintf(opts->out, "%010d %05d f \n", opts->ofslist[num], opts->genlist[num]);
+ }
+ fprintf(opts->out, "\n");
+
+ trailer = pdf_new_dict(ctx, 5);
+
+ obj = pdf_new_int(ctx, xref->len);
+ pdf_dict_puts(trailer, "Size", obj);
+ pdf_drop_obj(obj);
+
+ obj = pdf_dict_gets(xref->trailer, "Info");
+ if (obj)
+ pdf_dict_puts(trailer, "Info", obj);
+
+ obj = pdf_dict_gets(xref->trailer, "Root");
+ if (obj)
+ pdf_dict_puts(trailer, "Root", obj);
+
+ obj = pdf_dict_gets(xref->trailer, "ID");
+ if (obj)
+ pdf_dict_puts(trailer, "ID", obj);
+
+ fprintf(opts->out, "trailer\n");
+ pdf_fprint_obj(opts->out, trailer, opts->doexpand == 0);
+ fprintf(opts->out, "\n");
+
+ pdf_drop_obj(trailer);
+
+ fprintf(opts->out, "startxref\n%d\n%%%%EOF\n", startxref);
+}
+
+void pdf_write_document(pdf_document *xref, char *filename, fz_write_options *fz_opts)
+{
+ int lastfree;
+ int num;
+ pdf_write_options opts = { 0 };
+ fz_context *ctx;
+
+ if (!xref || !fz_opts)
+ return;
+
+ ctx = xref->ctx;
+
+ opts.out = fopen(filename, "wb");
+ if (!opts.out)
+ fz_throw(ctx, "cannot open output file '%s'", filename);
+
+ fz_try(ctx)
+ {
+ opts.doexpand = fz_opts ? fz_opts->doexpand : 0;
+ opts.dogarbage = fz_opts ? fz_opts->dogarbage : 0;
+ opts.doascii = fz_opts ? fz_opts->doascii: 0;
+ opts.uselist = fz_malloc_array(ctx, xref->len + 1, sizeof(char));
+ opts.ofslist = fz_malloc_array(ctx, xref->len + 1, sizeof(int));
+ opts.genlist = fz_malloc_array(ctx, xref->len + 1, sizeof(int));
+ opts.renumbermap = fz_malloc_array(ctx, xref->len + 1, sizeof(int));
+ opts.revrenumbermap = fz_malloc_array(ctx, xref->len + 1, sizeof(int));
+ opts.revgenlist = fz_malloc_array(ctx, xref->len + 1, sizeof(int));
+
+ fprintf(opts.out, "%%PDF-%d.%d\n", xref->version / 10, xref->version % 10);
+ fprintf(opts.out, "%%\316\274\341\277\246\n\n");
+
+ for (num = 0; num < xref->len; num++)
+ {
+ opts.uselist[num] = 0;
+ opts.ofslist[num] = 0;
+ opts.renumbermap[num] = num;
+ opts.revrenumbermap[num] = num;
+ opts.revgenlist[num] = xref->table[num].gen;
+ }
+
+ /* Make sure any objects hidden in compressed streams have been loaded */
+ preloadobjstms(xref);
+
+ /* Sweep & mark objects from the trailer */
+ if (opts.dogarbage >= 1)
+ sweepobj(xref, &opts, xref->trailer);
+
+ /* Coalesce and renumber duplicate objects */
+ if (opts.dogarbage >= 3)
+ removeduplicateobjs(xref, &opts);
+
+ /* Compact xref by renumbering and removing unused objects */
+ if (opts.dogarbage >= 2)
+ compactxref(xref, &opts);
+
+ /* Make renumbering affect all indirect references and update xref */
+ if (opts.dogarbage >= 2)
+ renumberobjs(xref, &opts);
+
+ for (num = 0; num < xref->len; num++)
+ {
+ if (xref->table[num].type == 'f')
+ opts.genlist[num] = xref->table[num].gen;
+ if (xref->table[num].type == 'n')
+ opts.genlist[num] = xref->table[num].gen;
+ if (xref->table[num].type == 'o')
+ opts.genlist[num] = 0;
+
+ if (opts.dogarbage && !opts.uselist[num])
+ continue;
+
+ if (xref->table[num].type == 'n' || xref->table[num].type == 'o')
+ {
+ opts.uselist[num] = 1;
+ opts.ofslist[num] = ftell(opts.out);
+ writeobject(xref, &opts, num, opts.genlist[num]);
+ }
+ }
+
+ /* Construct linked list of free object slots */
+ lastfree = 0;
+ for (num = 0; num < xref->len; num++)
+ {
+ if (!opts.uselist[num])
+ {
+ opts.genlist[num]++;
+ opts.ofslist[lastfree] = num;
+ lastfree = num;
+ }
+ }
+
+ writexref(xref, &opts);
+ }
+ fz_always(ctx)
+ {
+ fz_free(ctx, opts.uselist);
+ fz_free(ctx, opts.ofslist);
+ fz_free(ctx, opts.genlist);
+ fz_free(ctx, opts.renumbermap);
+ fz_free(ctx, opts.revrenumbermap);
+ fz_free(ctx, opts.revgenlist);
+ fclose(opts.out);
+ }
+ fz_catch(ctx)
+ {
+ fz_rethrow(ctx);
+ }
+}
diff --git a/pdf/pdf_xobject.c b/pdf/pdf_xobject.c
index 175f84b5..88ab5a01 100644
--- a/pdf/pdf_xobject.c
+++ b/pdf/pdf_xobject.c
@@ -23,7 +23,7 @@ pdf_free_xobject_imp(fz_context *ctx, fz_storable *xobj_)
if (xobj->resources)
pdf_drop_obj(xobj->resources);
if (xobj->contents)
- fz_drop_buffer(ctx, xobj->contents);
+ pdf_drop_obj(xobj->contents);
pdf_drop_obj(xobj->me);
fz_free(ctx, xobj);
}
@@ -33,7 +33,7 @@ pdf_xobject_size(pdf_xobject *xobj)
{
if (xobj == NULL)
return 0;
- return sizeof(*xobj) + (xobj->colorspace ? xobj->colorspace->size : 0) + (xobj->contents ? xobj->contents->len : 0);
+ return sizeof(*xobj) + (xobj->colorspace ? xobj->colorspace->size : 0);
}
pdf_xobject *
@@ -98,7 +98,7 @@ pdf_load_xobject(pdf_document *xref, pdf_obj *dict)
fz_try(ctx)
{
- form->contents = pdf_load_stream(xref, pdf_to_num(dict), pdf_to_gen(dict));
+ form->contents = pdf_keep_obj(dict);
}
fz_catch(ctx)
{
@@ -114,6 +114,7 @@ pdf_load_xobject(pdf_document *xref, pdf_obj *dict)
pdf_obj *
pdf_new_xobject(pdf_document *xref, fz_rect *bbox, fz_matrix *mat)
{
+ int idict_num;
pdf_obj *idict = NULL;
pdf_obj *dict = NULL;
pdf_xobject *form = NULL;
@@ -195,12 +196,15 @@ pdf_new_xobject(pdf_document *xref, fz_rect *bbox, fz_matrix *mat)
form->resources = res;
res = NULL;
- idict = pdf_new_stream_indirection(xref, dict);
+ idict_num = pdf_create_object(xref);
+ pdf_update_object(xref, idict_num, dict);
+ idict = pdf_new_indirect(ctx, idict_num, 0, xref);
pdf_drop_obj(dict);
dict = NULL;
pdf_store_item(ctx, idict, form, pdf_xobject_size(form));
+ form->contents = pdf_keep_obj(idict);
form->me = pdf_keep_obj(idict);
pdf_drop_xobject(ctx, form);
@@ -220,8 +224,8 @@ pdf_new_xobject(pdf_document *xref, fz_rect *bbox, fz_matrix *mat)
return idict;
}
-void pdf_xobject_set_contents(fz_context *ctx, pdf_xobject *form, fz_buffer *buffer)
+void pdf_xobject_set_contents(pdf_document *xref, pdf_xobject *form, fz_buffer *buffer)
{
- fz_drop_buffer(ctx, form->contents);
- form->contents = fz_keep_buffer(ctx, buffer);
+ pdf_dict_dels(form->contents, "Filter");
+ pdf_update_stream(xref, pdf_to_num(form->contents), buffer);
}
diff --git a/pdf/pdf_xref.c b/pdf/pdf_xref.c
index cd15051c..ea99d3c2 100644
--- a/pdf/pdf_xref.c
+++ b/pdf/pdf_xref.c
@@ -173,6 +173,7 @@ pdf_resize_xref(pdf_document *xref, int newlen)
xref->table[i].ofs = 0;
xref->table[i].gen = 0;
xref->table[i].stm_ofs = 0;
+ xref->table[i].stm_buf = NULL;
xref->table[i].obj = NULL;
}
xref->len = newlen;
@@ -293,8 +294,7 @@ pdf_read_new_xref_section(pdf_document *xref, fz_stream *stm, int i0, int i1, in
}
}
-/* Entered with file locked. Drops the lock in the middle, but then picks
- * it up again before exiting. */
+/* Entered with file locked, remains locked throughout. */
static pdf_obj *
pdf_read_new_xref(pdf_document *xref, pdf_lexbuf *buf)
{
@@ -321,7 +321,6 @@ pdf_read_new_xref(pdf_document *xref, pdf_lexbuf *buf)
fz_try(ctx)
{
- fz_unlock(ctx, FZ_LOCK_FILE);
obj = pdf_dict_gets(trailer, "Size");
if (!obj)
fz_throw(ctx, "xref stream missing Size entry (%d %d R)", num, gen);
@@ -371,7 +370,6 @@ pdf_read_new_xref(pdf_document *xref, pdf_lexbuf *buf)
pdf_drop_obj(index);
fz_rethrow(ctx);
}
- fz_lock(ctx, FZ_LOCK_FILE);
return trailer;
}
@@ -410,13 +408,13 @@ static void
pdf_read_xref_sections(pdf_document *xref, int ofs, pdf_lexbuf *buf)
{
pdf_obj *trailer = NULL;
- pdf_obj *xrefstm = NULL;
- pdf_obj *prev = NULL;
fz_context *ctx = xref->ctx;
+ int xrefstmofs = 0;
+ int prevofs = 0;
fz_var(trailer);
- fz_var(xrefstm);
- fz_var(prev);
+ fz_var(xrefstmofs);
+ fz_var(prevofs);
fz_try(ctx)
{
@@ -425,20 +423,21 @@ pdf_read_xref_sections(pdf_document *xref, int ofs, pdf_lexbuf *buf)
trailer = pdf_read_xref(xref, ofs, buf);
/* FIXME: do we overwrite free entries properly? */
- xrefstm = pdf_dict_gets(trailer, "XRefStm");
- prev = pdf_dict_gets(trailer, "Prev");
+ xrefstmofs = pdf_to_int(pdf_dict_gets(trailer, "XRefStm"));
+ prevofs = pdf_to_int(pdf_dict_gets(trailer, "Prev"));
+
/* We only recurse if we have both xrefstm and prev.
* Hopefully this happens infrequently. */
- if (xrefstm && prev)
- pdf_read_xref_sections(xref, pdf_to_int(xrefstm), buf);
- if (prev)
- ofs = pdf_to_int(prev);
- else if (xrefstm)
- ofs = pdf_to_int(xrefstm);
+ if (xrefstmofs && prevofs)
+ pdf_read_xref_sections(xref, xrefstmofs, buf);
+ if (prevofs)
+ ofs = prevofs;
+ else if (xrefstmofs)
+ ofs = xrefstmofs;
pdf_drop_obj(trailer);
trailer = NULL;
}
- while (prev || xrefstm);
+ while (prevofs || xrefstmofs);
}
fz_catch(ctx)
{
@@ -449,12 +448,14 @@ pdf_read_xref_sections(pdf_document *xref, int ofs, pdf_lexbuf *buf)
/*
* load xref tables from pdf
+ *
+ * File locked on entry, throughout and on exit.
*/
static void
pdf_load_xref(pdf_document *xref, pdf_lexbuf *buf)
{
- pdf_obj *size;
+ int size;
int i;
fz_context *ctx = xref->ctx;
@@ -464,11 +465,11 @@ pdf_load_xref(pdf_document *xref, pdf_lexbuf *buf)
pdf_read_trailer(xref, buf);
- size = pdf_dict_gets(xref->trailer, "Size");
+ size = pdf_to_int(pdf_dict_gets(xref->trailer, "Size"));
if (!size)
fz_throw(ctx, "trailer missing Size entry");
- pdf_resize_xref(xref, pdf_to_int(size));
+ pdf_resize_xref(xref, size);
pdf_read_xref_sections(xref, xref->startxref, buf);
@@ -660,33 +661,18 @@ pdf_free_ocg(fz_context *ctx, pdf_ocg_descriptor *desc)
* If password is not null, try to decrypt.
*/
-static void pdf_init_document(pdf_document *xref);
-
-pdf_document *
-pdf_open_document_with_stream(fz_stream *file)
+static void
+pdf_init_document(pdf_document *xref)
{
- pdf_document *xref;
+ fz_context *ctx = xref->ctx;
pdf_obj *encrypt, *id;
pdf_obj *dict = NULL;
pdf_obj *obj;
pdf_obj *nobj = NULL;
int i, repaired = 0;
- int locked;
- fz_context *ctx = file->ctx;
fz_var(dict);
fz_var(nobj);
- fz_var(locked);
-
- xref = fz_malloc_struct(ctx, pdf_document);
- pdf_init_document(xref);
- xref->lexbuf.base.size = PDF_LEXBUF_LARGE;
-
- xref->file = fz_keep_stream(file);
- xref->ctx = ctx;
-
- fz_lock(ctx, FZ_LOCK_FILE);
- locked = 1;
fz_try(ctx)
{
@@ -717,9 +703,6 @@ pdf_open_document_with_stream(fz_stream *file)
if (repaired)
pdf_repair_xref(xref, &xref->lexbuf.base);
- fz_unlock(ctx, FZ_LOCK_FILE);
- locked = 0;
-
encrypt = pdf_dict_gets(xref->trailer, "Encrypt");
id = pdf_dict_gets(xref->trailer, "ID");
if (pdf_is_dict(encrypt))
@@ -778,11 +761,6 @@ pdf_open_document_with_stream(fz_stream *file)
}
}
}
- fz_always(ctx)
- {
- if (locked)
- fz_unlock(ctx, FZ_LOCK_FILE);
- }
fz_catch(ctx)
{
pdf_drop_obj(dict);
@@ -799,8 +777,6 @@ pdf_open_document_with_stream(fz_stream *file)
{
fz_warn(ctx, "Ignoring Broken Optional Content");
}
-
- return xref;
}
void
@@ -865,11 +841,12 @@ pdf_print_xref(pdf_document *xref)
printf("xref\n0 %d\n", xref->len);
for (i = 0; i < xref->len; i++)
{
- printf("%05d: %010d %05d %c (stm_ofs=%d)\n", i,
+ printf("%05d: %010d %05d %c (stm_ofs=%d; stm_buf=%p)\n", i,
xref->table[i].ofs,
xref->table[i].gen,
xref->table[i].type ? xref->table[i].type : '-',
- xref->table[i].stm_ofs);
+ xref->table[i].stm_ofs,
+ xref->table[i].stm_buf);
}
}
@@ -987,7 +964,6 @@ pdf_cache_object(pdf_document *xref, int num, int gen)
}
else if (x->type == 'n')
{
- fz_lock(ctx, FZ_LOCK_FILE);
fz_seek(xref->file, x->ofs, 0);
fz_try(ctx)
@@ -997,7 +973,6 @@ pdf_cache_object(pdf_document *xref, int num, int gen)
}
fz_catch(ctx)
{
- fz_unlock(ctx, FZ_LOCK_FILE);
fz_throw(ctx, "cannot parse object (%d %d R)", num, gen);
}
@@ -1005,13 +980,11 @@ pdf_cache_object(pdf_document *xref, int num, int gen)
{
pdf_drop_obj(x->obj);
x->obj = NULL;
- fz_unlock(ctx, FZ_LOCK_FILE);
fz_throw(ctx, "found object (%d %d R) instead of (%d %d R)", rnum, rgen, num, gen);
}
if (xref->crypt)
pdf_crypt_obj(ctx, xref->crypt, x->obj, num, gen);
- fz_unlock(ctx, FZ_LOCK_FILE);
}
else if (x->type == 'o')
{
@@ -1093,127 +1066,105 @@ pdf_resolve_indirect(pdf_obj *ref)
return ref;
}
-int pdf_count_objects(pdf_document *doc)
+int
+pdf_count_objects(pdf_document *doc)
{
return doc->len;
}
-/* Replace numbered object -- for use by pdfclean and similar tools */
+int
+pdf_create_object(pdf_document *xref)
+{
+ /* TODO: reuse free object slots by properly linking free object chains in the ofs field */
+ int num = xref->len;
+ pdf_resize_xref(xref, num + 1);
+ xref->table[num].type = 'f';
+ xref->table[num].ofs = -1;
+ xref->table[num].gen = 0;
+ xref->table[num].stm_ofs = 0;
+ xref->table[num].stm_buf = NULL;
+ xref->table[num].obj = NULL;
+ return num;
+}
+
void
-pdf_update_object(pdf_document *xref, int num, int gen, pdf_obj *newobj)
+pdf_delete_object(pdf_document *xref, int num)
{
pdf_xref_entry *x;
if (num < 0 || num >= xref->len)
{
- fz_warn(xref->ctx, "object out of range (%d %d R); xref size %d", num, gen, xref->len);
+ fz_warn(xref->ctx, "object out of range (%d 0 R); xref size %d", num, xref->len);
return;
}
x = &xref->table[num];
- if (x->obj)
- pdf_drop_obj(x->obj);
+ fz_drop_buffer(xref->ctx, x->stm_buf);
+ pdf_drop_obj(x->obj);
- x->obj = pdf_keep_obj(newobj);
- x->type = 'n';
+ x->type = 'f';
x->ofs = 0;
+ x->gen = 0;
+ x->stm_ofs = 0;
+ x->stm_buf = NULL;
+ x->obj = NULL;
}
-pdf_obj *
-pdf_new_stream_indirection(pdf_document *xref, pdf_obj *obj)
-{
- int num = xref->len;
- pdf_resize_xref(xref, xref->len + 1);
- pdf_update_object(xref, num, 0, obj);
- /* Set stm_ofs, so that obj is treated as a stream */
- xref->table[num].stm_ofs = 1;
-
- return pdf_new_indirect(xref->ctx, num, 0, xref);
-}
-
-/*
- * Convenience function to open a file then call pdf_open_document_with_stream.
- */
-
-pdf_document *
-pdf_open_document(fz_context *ctx, const char *filename)
+void
+pdf_update_object(pdf_document *xref, int num, pdf_obj *newobj)
{
- fz_stream *file = NULL;
- pdf_document *xref;
+ pdf_xref_entry *x;
- fz_var(file);
- fz_try(ctx)
- {
- file = fz_open_file(ctx, filename);
- xref = pdf_open_document_with_stream(file);
- }
- fz_catch(ctx)
+ if (num < 0 || num >= xref->len)
{
- fz_close(file);
- fz_throw(ctx, "cannot load document '%s'", filename);
+ fz_warn(xref->ctx, "object out of range (%d 0 R); xref size %d", num, xref->len);
+ return;
}
- fz_close(file);
- return xref;
-}
-
-/* Document interface wrappers */
+ x = &xref->table[num];
-static void pdf_close_document_shim(fz_document *doc)
-{
- pdf_close_document((pdf_document*)doc);
-}
+ if (x->obj)
+ pdf_drop_obj(x->obj);
-static int pdf_needs_password_shim(fz_document *doc)
-{
- return pdf_needs_password((pdf_document*)doc);
+ x->type = 'n';
+ x->ofs = 0;
+ x->obj = pdf_keep_obj(newobj);
}
-static int pdf_authenticate_password_shim(fz_document *doc, char *password)
+fz_buffer *
+pdf_get_stream(pdf_document *xref, int num)
{
- return pdf_authenticate_password((pdf_document*)doc, password);
-}
+ pdf_xref_entry *x;
-static fz_outline *pdf_load_outline_shim(fz_document *doc)
-{
- return pdf_load_outline((pdf_document*)doc);
-}
+ if (num < 0 || num >= xref->len)
+ fz_throw(xref->ctx, "object out of range (%d 0 R); xref size %d", num, xref->len);
-static int pdf_count_pages_shim(fz_document *doc)
-{
- return pdf_count_pages((pdf_document*)doc);
-}
+ x = &xref->table[num];
-static fz_page *pdf_load_page_shim(fz_document *doc, int number)
-{
- return (fz_page*) pdf_load_page((pdf_document*)doc, number);
+ return x->stm_buf;
}
-static fz_link *pdf_load_links_shim(fz_document *doc, fz_page *page)
+void
+pdf_update_stream(pdf_document *xref, int num, fz_buffer *newbuf)
{
- return pdf_load_links((pdf_document*)doc, (pdf_page*)page);
-}
+ pdf_xref_entry *x;
-static fz_rect pdf_bound_page_shim(fz_document *doc, fz_page *page)
-{
- return pdf_bound_page((pdf_document*)doc, (pdf_page*)page);
-}
+ if (num < 0 || num >= xref->len)
+ {
+ fz_warn(xref->ctx, "object out of range (%d 0 R); xref size %d", num, xref->len);
+ return;
+ }
-static void pdf_run_page_shim(fz_document *doc, fz_page *page, fz_device *dev, fz_matrix transform, fz_cookie *cookie)
-{
- pdf_run_page((pdf_document*)doc, (pdf_page*)page, dev, transform, cookie);
-}
+ x = &xref->table[num];
-static void pdf_free_page_shim(fz_document *doc, fz_page *page)
-{
- pdf_free_page((pdf_document*)doc, (pdf_page*)page);
+ fz_drop_buffer(xref->ctx, x->stm_buf);
+ x->stm_buf = fz_keep_buffer(xref->ctx, newbuf);
}
-static int pdf_meta(fz_document *doc_, int key, void *ptr, int size)
+int
+pdf_meta(pdf_document *doc, int key, void *ptr, int size)
{
- pdf_document *doc = (pdf_document *)doc_;
-
switch(key)
{
/*
@@ -1295,9 +1246,72 @@ static fz_interactive *pdf_interact_shim(fz_document *doc)
return (fz_interactive *)doc;
}
-static void
-pdf_init_document(pdf_document *doc)
+/*
+ Wrappers to implement the fz_document interface for pdf_document.
+
+ The functions are split across two files to allow calls to a
+ version of the constructor that does not link in the interpreter.
+ The interpreter references the built-in font and cmap resources
+ which are quite big. Not linking those into the mubusy binary
+ saves roughly 6MB of space.
+*/
+
+static void pdf_close_document_shim(fz_document *doc)
{
+ pdf_close_document((pdf_document*)doc);
+}
+
+static int pdf_needs_password_shim(fz_document *doc)
+{
+ return pdf_needs_password((pdf_document*)doc);
+}
+
+static int pdf_authenticate_password_shim(fz_document *doc, char *password)
+{
+ return pdf_authenticate_password((pdf_document*)doc, password);
+}
+
+static fz_outline *pdf_load_outline_shim(fz_document *doc)
+{
+ return pdf_load_outline((pdf_document*)doc);
+}
+
+static int pdf_count_pages_shim(fz_document *doc)
+{
+ return pdf_count_pages((pdf_document*)doc);
+}
+
+static fz_page *pdf_load_page_shim(fz_document *doc, int number)
+{
+ return (fz_page*) pdf_load_page((pdf_document*)doc, number);
+}
+
+static fz_link *pdf_load_links_shim(fz_document *doc, fz_page *page)
+{
+ return pdf_load_links((pdf_document*)doc, (pdf_page*)page);
+}
+
+static fz_rect pdf_bound_page_shim(fz_document *doc, fz_page *page)
+{
+ return pdf_bound_page((pdf_document*)doc, (pdf_page*)page);
+}
+
+static void pdf_free_page_shim(fz_document *doc, fz_page *page)
+{
+ pdf_free_page((pdf_document*)doc, (pdf_page*)page);
+}
+
+static int pdf_meta_shim(fz_document *doc, int key, void *ptr, int size)
+{
+ return pdf_meta((pdf_document*)doc, key, ptr, size);
+}
+
+static pdf_document *
+pdf_new_document(fz_stream *file)
+{
+ fz_context *ctx = file->ctx;
+ pdf_document *doc = fz_malloc_struct(ctx, pdf_document);
+
doc->super.close = pdf_close_document_shim;
doc->super.needs_password = pdf_needs_password_shim;
doc->super.authenticate_password = pdf_authenticate_password_shim;
@@ -1306,8 +1320,47 @@ pdf_init_document(pdf_document *doc)
doc->super.load_page = pdf_load_page_shim;
doc->super.load_links = pdf_load_links_shim;
doc->super.bound_page = pdf_bound_page_shim;
- doc->super.run_page = pdf_run_page_shim;
+ doc->super.run_page = NULL; /* see pdf_xref_aux.c */
doc->super.free_page = pdf_free_page_shim;
- doc->super.meta = pdf_meta;
+ doc->super.meta = pdf_meta_shim;
doc->super.interact = pdf_interact_shim;
+
+ doc->lexbuf.base.size = PDF_LEXBUF_LARGE;
+ doc->file = fz_keep_stream(file);
+ doc->ctx = ctx;
+
+ return doc;
+}
+
+pdf_document *
+pdf_open_document_no_run_with_stream(fz_stream *file)
+{
+ pdf_document *doc = pdf_new_document(file);
+ pdf_init_document(doc);
+ return doc;
+}
+
+pdf_document *
+pdf_open_document_no_run(fz_context *ctx, const char *filename)
+{
+ fz_stream *file = NULL;
+ pdf_document *doc;
+
+ fz_var(file);
+
+ fz_try(ctx)
+ {
+ file = fz_open_file(ctx, filename);
+ doc = pdf_new_document(file);
+ pdf_init_document(doc);
+ }
+ fz_always(ctx)
+ {
+ fz_close(file);
+ }
+ fz_catch(ctx)
+ {
+ fz_throw(ctx, "cannot load document '%s'", filename);
+ }
+ return doc;
}
diff --git a/pdf/pdf_xref_aux.c b/pdf/pdf_xref_aux.c
new file mode 100644
index 00000000..2d760334
--- /dev/null
+++ b/pdf/pdf_xref_aux.c
@@ -0,0 +1,31 @@
+#include "fitz-internal.h"
+#include "mupdf-internal.h"
+
+/*
+ These functions have been split out of pdf_xref.c to allow tools
+ to be linked without pulling in the interpreter. The interpreter
+ references the built-in font and cmap resources which are quite
+ big. Not linking those into the tools saves roughly 6MB in the
+ resulting executables.
+*/
+
+static void pdf_run_page_shim(fz_document *doc, fz_page *page, fz_device *dev, fz_matrix transform, fz_cookie *cookie)
+{
+ pdf_run_page((pdf_document*)doc, (pdf_page*)page, dev, transform, cookie);
+}
+
+pdf_document *
+pdf_open_document_with_stream(fz_stream *file)
+{
+ pdf_document *doc = pdf_open_document_no_run_with_stream(file);
+ doc->super.run_page = pdf_run_page_shim;
+ return doc;
+}
+
+pdf_document *
+pdf_open_document(fz_context *ctx, const char *filename)
+{
+ pdf_document *doc = pdf_open_document_no_run(ctx, filename);
+ doc->super.run_page = pdf_run_page_shim;
+ return doc;
+}
diff --git a/scripts/cmapdump.c b/scripts/cmapdump.c
index 57cfe54b..53247339 100644
--- a/scripts/cmapdump.c
+++ b/scripts/cmapdump.c
@@ -85,7 +85,6 @@ main(int argc, char **argv)
clean(name);
fi = fz_open_file(ctx, argv[i]);
- fz_lock_stream(fi);
cmap = pdf_load_cmap(ctx, fi);
fz_close(fi);
diff --git a/scripts/runtohtml.sh b/scripts/runtohtml.sh
new file mode 100644
index 00000000..9b94e22b
--- /dev/null
+++ b/scripts/runtohtml.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+mkdir -p doc/source
+rm doc/source/*.html
+
+FILES="fitz/*.[ch] draw/*.[ch] pdf/*.[ch] xps/*.[ch] cbz/*.[ch] apps/*.[ch]"
+
+echo running ctags to make xref
+ctags -x $FILES > tags-xref
+
+for input in $FILES
+do
+ output=doc/source/$(basename $input).html
+ echo $input $output
+ python scripts/tohtml.py < $input > $output
+done
+
+rm tags-xref
diff --git a/scripts/tohtml.py b/scripts/tohtml.py
new file mode 100644
index 00000000..6ad22ecd
--- /dev/null
+++ b/scripts/tohtml.py
@@ -0,0 +1,66 @@
+import sys, os, re
+
+HEADER="""<head>
+<style>
+body { background-color:#fffff0; color:black; margin:16pt; }
+a { text-decoration:none; color:darkblue; }
+a.line { position:relative; padding-top:300px; }
+.comment { color:green; font-style:italic; }
+.comment a { color:darkgreen; }
+</style>
+</head>
+<body><pre><pre>"""
+
+FOOTER="""</pre></body>"""
+
+prefixes = [ 'fz_', 'pdf_', 'xps_', 'cbz_', 'pdfapp_' ]
+
+def is_public(s):
+ for prefix in prefixes:
+ if s.startswith(prefix):
+ return True
+ return False
+
+def load_tags():
+ tags = {}
+ for line in open("tags-xref").readlines():
+ ident, type, line, file, text = line.split(None, 4)
+ if not is_public(ident):
+ continue
+ if type == 'function':
+ tags[ident] = '<a class="function" href="%s#%s">%s</a>' % (os.path.basename(file), line, ident)
+ if type == 'typedef' or type == 'struct':
+ tags[ident] = '<a class="typedef" href="%s#%s">%s</a>' % (os.path.basename(file), line, ident)
+ return tags
+
+tags = load_tags()
+
+def quote(s):
+ return s.replace('&','&amp;').replace('<','&lt;').replace('>','&gt;')
+
+print HEADER
+
+N = 1
+for line in sys.stdin.readlines():
+ # expand tabs, html-quote special characters and colorize comments
+ line = line.replace('\t', ' ').rstrip()
+ line = quote(line)
+ line = line.replace("/*", '<span class="comment">/*')
+ line = line.replace("*/", '*/</span>')
+
+ line = re.sub('^#include "([a-z-]*\.h)"', '#include "<a href="\\1">\\1</a>"', line)
+
+ # find identifiers and hyperlink to their definitions
+ words = re.split("(\W+)", line)
+ line = ""
+ for word in words:
+ if word in tags:
+ word = tags[word]
+ line += word
+
+ #print('<a class="line" name="%d">%4d</a> %s' % (N, N, line))
+ print('<a class="line" name="%d"></a>%s' % (N, line))
+
+ N = N + 1
+
+print FOOTER
diff --git a/win32/libmupdf-v8.vcproj b/win32/libmupdf-v8.vcproj
index af20539a..9a7baf54 100644
--- a/win32/libmupdf-v8.vcproj
+++ b/win32/libmupdf-v8.vcproj
@@ -211,10 +211,6 @@
Name="pdf"
>
<File
- RelativePath="..\pdf\base_object.c"
- >
- </File>
- <File
RelativePath="..\pdf\data_encodings.h"
>
</File>
@@ -315,6 +311,10 @@
>
</File>
<File
+ RelativePath="..\pdf\pdf_object.c"
+ >
+ </File>
+ <File
RelativePath="..\pdf\pdf_outline.c"
>
</File>
@@ -362,6 +362,10 @@
RelativePath="..\pdf\pdf_xref.c"
>
</File>
+ <File
+ RelativePath="..\pdf\pdf_xref_aux.c"
+ >
+ </File>
</Filter>
<Filter
Name="fitz"
diff --git a/win32/libmupdf.vcproj b/win32/libmupdf.vcproj
index 2bd67845..a15c8cb0 100644
--- a/win32/libmupdf.vcproj
+++ b/win32/libmupdf.vcproj
@@ -210,10 +210,6 @@
Name="pdf"
>
<File
- RelativePath="..\pdf\base_object.c"
- >
- </File>
- <File
RelativePath="..\pdf\data_encodings.h"
>
</File>
@@ -302,6 +298,10 @@
>
</File>
<File
+ RelativePath="..\pdf\pdf_object.c"
+ >
+ </File>
+ <File
RelativePath="..\pdf\pdf_outline.c"
>
</File>
@@ -342,6 +342,10 @@
>
</File>
<File
+ RelativePath="..\pdf\pdf_write.c"
+ >
+ </File>
+ <File
RelativePath="..\pdf\pdf_xobject.c"
>
</File>
@@ -349,6 +353,10 @@
RelativePath="..\pdf\pdf_xref.c"
>
</File>
+ <File
+ RelativePath="..\pdf\pdf_xref_aux.c"
+ >
+ </File>
</Filter>
<Filter
Name="fitz"
diff --git a/win32/mubusy.vcproj b/win32/mubusy.vcproj
index f7d27360..c905681e 100644
--- a/win32/mubusy.vcproj
+++ b/win32/mubusy.vcproj
@@ -241,23 +241,23 @@
>
</File>
<File
- RelativePath="..\apps\mubusy_draw.c"
+ RelativePath="..\apps\mupdfclean.c"
>
</File>
<File
- RelativePath="..\apps\mubusy_pdfclean.c"
+ RelativePath="..\apps\mupdfextract.c"
>
</File>
<File
- RelativePath="..\apps\mubusy_pdfextract.c"
+ RelativePath="..\apps\mupdfinfo.c"
>
</File>
<File
- RelativePath="..\apps\mubusy_pdfinfo.c"
+ RelativePath="..\apps\mupdfposter.c"
>
</File>
<File
- RelativePath="..\apps\mubusy_pdfshow.c"
+ RelativePath="..\apps\mupdfshow.c"
>
</File>
</Files>
diff --git a/win32/mupdf.sln b/win32/mupdf.sln
index c6e03880..ef64e779 100644
--- a/win32/mupdf.sln
+++ b/win32/mupdf.sln
@@ -3,8 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupdf", "mupdf.vcproj", "{E74F29F0-FA43-4ADC-B92C-6AFA08E4A417}"
ProjectSection(ProjectDependencies) = postProject
- {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C} = {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C}
{5F615F91-DFF8-4F05-BF48-6222B7D86519} = {5F615F91-DFF8-4F05-BF48-6222B7D86519}
+ {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C} = {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libthirdparty", "libthirdparty.vcproj", "{5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C}"
@@ -16,44 +16,23 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmupdf", "libmupdf.vcproj
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mudraw", "mudraw.vcproj", "{0B51171B-B10E-4EAC-8FFA-19226A1828A3}"
ProjectSection(ProjectDependencies) = postProject
- {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C} = {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C}
- {5F615F91-DFF8-4F05-BF48-6222B7D86519} = {5F615F91-DFF8-4F05-BF48-6222B7D86519}
{A5053AA7-02E5-4903-B596-04F17AEB1526} = {A5053AA7-02E5-4903-B596-04F17AEB1526}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupdfclean", "mupdfclean.vcproj", "{923D7C3D-A5CD-47F1-9BB3-F716531DCCCE}"
- ProjectSection(ProjectDependencies) = postProject
- {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C} = {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C}
- {5F615F91-DFF8-4F05-BF48-6222B7D86519} = {5F615F91-DFF8-4F05-BF48-6222B7D86519}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupdfshow", "mupdfshow.vcproj", "{50644121-C85F-4EE9-9C54-F7D1BDFAE354}"
- ProjectSection(ProjectDependencies) = postProject
- {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C} = {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C}
- {5F615F91-DFF8-4F05-BF48-6222B7D86519} = {5F615F91-DFF8-4F05-BF48-6222B7D86519}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupdfextract", "mupdfextract.vcproj", "{BD4473E7-2DBE-4568-A0FC-38EED70182DC}"
- ProjectSection(ProjectDependencies) = postProject
- {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C} = {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C}
- {5F615F91-DFF8-4F05-BF48-6222B7D86519} = {5F615F91-DFF8-4F05-BF48-6222B7D86519}
- EndProjectSection
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupdfinfo", "mupdfinfo.vcproj", "{E7578F65-AA5B-43A3-981A-D3632C2A3C04}"
- ProjectSection(ProjectDependencies) = postProject
{5F615F91-DFF8-4F05-BF48-6222B7D86519} = {5F615F91-DFF8-4F05-BF48-6222B7D86519}
{5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C} = {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mubusy", "mubusy.vcproj", "{00811970-815B-4F64-BC9D-219078B1F3AA}"
ProjectSection(ProjectDependencies) = postProject
- {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C} = {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C}
{5F615F91-DFF8-4F05-BF48-6222B7D86519} = {5F615F91-DFF8-4F05-BF48-6222B7D86519}
+ {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C} = {5EDCF4FD-0291-4FB9-8D96-D58957CA5E3C}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "generated", "generated.vcproj", "{A5053AA7-02E5-4903-B596-04F17AEB1526}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmupdf-v8", "libmupdf-v8.vcproj", "{2E5DAFDB-A060-4011-B760-32F6A3A4BC9D}"
+ ProjectSection(ProjectDependencies) = postProject
+ {A5053AA7-02E5-4903-B596-04F17AEB1526} = {A5053AA7-02E5-4903-B596-04F17AEB1526}
+ EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mupdf-v8", "mupdf-v8.vcproj", "{9035A4F3-4219-45A5-985D-FBF4D9609713}"
ProjectSection(ProjectDependencies) = postProject
@@ -92,30 +71,6 @@ Global
{0B51171B-B10E-4EAC-8FFA-19226A1828A3}.Memento|Win32.Build.0 = Memento|Win32
{0B51171B-B10E-4EAC-8FFA-19226A1828A3}.Release|Win32.ActiveCfg = Release|Win32
{0B51171B-B10E-4EAC-8FFA-19226A1828A3}.Release|Win32.Build.0 = Release|Win32
- {923D7C3D-A5CD-47F1-9BB3-F716531DCCCE}.Debug|Win32.ActiveCfg = Debug|Win32
- {923D7C3D-A5CD-47F1-9BB3-F716531DCCCE}.Debug|Win32.Build.0 = Debug|Win32
- {923D7C3D-A5CD-47F1-9BB3-F716531DCCCE}.Memento|Win32.ActiveCfg = Memento|Win32
- {923D7C3D-A5CD-47F1-9BB3-F716531DCCCE}.Memento|Win32.Build.0 = Memento|Win32
- {923D7C3D-A5CD-47F1-9BB3-F716531DCCCE}.Release|Win32.ActiveCfg = Release|Win32
- {923D7C3D-A5CD-47F1-9BB3-F716531DCCCE}.Release|Win32.Build.0 = Release|Win32
- {50644121-C85F-4EE9-9C54-F7D1BDFAE354}.Debug|Win32.ActiveCfg = Debug|Win32
- {50644121-C85F-4EE9-9C54-F7D1BDFAE354}.Debug|Win32.Build.0 = Debug|Win32
- {50644121-C85F-4EE9-9C54-F7D1BDFAE354}.Memento|Win32.ActiveCfg = Memento|Win32
- {50644121-C85F-4EE9-9C54-F7D1BDFAE354}.Memento|Win32.Build.0 = Memento|Win32
- {50644121-C85F-4EE9-9C54-F7D1BDFAE354}.Release|Win32.ActiveCfg = Release|Win32
- {50644121-C85F-4EE9-9C54-F7D1BDFAE354}.Release|Win32.Build.0 = Release|Win32
- {BD4473E7-2DBE-4568-A0FC-38EED70182DC}.Debug|Win32.ActiveCfg = Debug|Win32
- {BD4473E7-2DBE-4568-A0FC-38EED70182DC}.Debug|Win32.Build.0 = Debug|Win32
- {BD4473E7-2DBE-4568-A0FC-38EED70182DC}.Memento|Win32.ActiveCfg = Memento|Win32
- {BD4473E7-2DBE-4568-A0FC-38EED70182DC}.Memento|Win32.Build.0 = Memento|Win32
- {BD4473E7-2DBE-4568-A0FC-38EED70182DC}.Release|Win32.ActiveCfg = Release|Win32
- {BD4473E7-2DBE-4568-A0FC-38EED70182DC}.Release|Win32.Build.0 = Release|Win32
- {E7578F65-AA5B-43A3-981A-D3632C2A3C04}.Debug|Win32.ActiveCfg = Debug|Win32
- {E7578F65-AA5B-43A3-981A-D3632C2A3C04}.Debug|Win32.Build.0 = Debug|Win32
- {E7578F65-AA5B-43A3-981A-D3632C2A3C04}.Memento|Win32.ActiveCfg = Memento|Win32
- {E7578F65-AA5B-43A3-981A-D3632C2A3C04}.Memento|Win32.Build.0 = Memento|Win32
- {E7578F65-AA5B-43A3-981A-D3632C2A3C04}.Release|Win32.ActiveCfg = Release|Win32
- {E7578F65-AA5B-43A3-981A-D3632C2A3C04}.Release|Win32.Build.0 = Release|Win32
{00811970-815B-4F64-BC9D-219078B1F3AA}.Debug|Win32.ActiveCfg = Debug|Win32
{00811970-815B-4F64-BC9D-219078B1F3AA}.Debug|Win32.Build.0 = Debug|Win32
{00811970-815B-4F64-BC9D-219078B1F3AA}.Memento|Win32.ActiveCfg = Memento|Win32
diff --git a/win32/mupdfclean.vcproj b/win32/mupdfclean.vcproj
deleted file mode 100644
index db8c8f3c..00000000
--- a/win32/mupdfclean.vcproj
+++ /dev/null
@@ -1,246 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="8.00"
- Name="mupdfclean"
- ProjectGUID="{923D7C3D-A5CD-47F1-9BB3-F716531DCCCE}"
- RootNamespace="mupdf"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
- ConfigurationType="1"
- CharacterSet="2"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories="..\fitz;..\pdf"
- PreprocessorDefinitions="DEBUG=1"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- WarningLevel="3"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- GenerateDebugInformation="true"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
- ConfigurationType="1"
- CharacterSet="2"
- WholeProgramOptimization="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="2"
- EnableIntrinsicFunctions="true"
- AdditionalIncludeDirectories="..\fitz;..\pdf"
- RuntimeLibrary="0"
- EnableFunctionLevelLinking="true"
- WarningLevel="3"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- GenerateDebugInformation="true"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Memento|Win32"
- OutputDirectory="$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
- ConfigurationType="1"
- CharacterSet="2"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories="..\fitz;..\pdf"
- PreprocessorDefinitions="MEMENTO=1;DEBUG=1"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- WarningLevel="3"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- GenerateDebugInformation="true"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <File
- RelativePath="..\apps\mupdfclean.c"
- >
- </File>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
diff --git a/win32/mupdfextract.vcproj b/win32/mupdfextract.vcproj
deleted file mode 100644
index 04251c15..00000000
--- a/win32/mupdfextract.vcproj
+++ /dev/null
@@ -1,246 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="8.00"
- Name="mupdfextract"
- ProjectGUID="{BD4473E7-2DBE-4568-A0FC-38EED70182DC}"
- RootNamespace="mupdf"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
- ConfigurationType="1"
- CharacterSet="2"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories="..\fitz;..\pdf"
- PreprocessorDefinitions="DEBUG=1"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- WarningLevel="3"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- GenerateDebugInformation="true"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
- ConfigurationType="1"
- CharacterSet="2"
- WholeProgramOptimization="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="2"
- EnableIntrinsicFunctions="true"
- AdditionalIncludeDirectories="..\fitz;..\pdf"
- RuntimeLibrary="0"
- EnableFunctionLevelLinking="true"
- WarningLevel="3"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- GenerateDebugInformation="true"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Memento|Win32"
- OutputDirectory="$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
- ConfigurationType="1"
- CharacterSet="2"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories="..\fitz;..\pdf"
- PreprocessorDefinitions="MEMENTO=1;DEBUG=1"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- WarningLevel="3"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- GenerateDebugInformation="true"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <File
- RelativePath="..\apps\mupdfextract.c"
- >
- </File>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
diff --git a/win32/mupdfinfo.vcproj b/win32/mupdfinfo.vcproj
deleted file mode 100644
index ad8b960b..00000000
--- a/win32/mupdfinfo.vcproj
+++ /dev/null
@@ -1,246 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="8.00"
- Name="mupdfinfo"
- ProjectGUID="{E7578F65-AA5B-43A3-981A-D3632C2A3C04}"
- RootNamespace="mupdf"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
- ConfigurationType="1"
- CharacterSet="2"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories="..\fitz;..\pdf"
- PreprocessorDefinitions="DEBUG=1"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- WarningLevel="3"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- GenerateDebugInformation="true"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
- ConfigurationType="1"
- CharacterSet="2"
- WholeProgramOptimization="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="2"
- EnableIntrinsicFunctions="true"
- AdditionalIncludeDirectories="..\fitz;..\pdf"
- RuntimeLibrary="0"
- EnableFunctionLevelLinking="true"
- WarningLevel="3"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- GenerateDebugInformation="true"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Memento|Win32"
- OutputDirectory="$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
- ConfigurationType="1"
- CharacterSet="2"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories="..\fitz;..\pdf"
- PreprocessorDefinitions="MEMENTO=1;DEBUG=1"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- WarningLevel="3"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- GenerateDebugInformation="true"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <File
- RelativePath="..\apps\mupdfinfo.c"
- >
- </File>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
diff --git a/win32/mupdfshow.vcproj b/win32/mupdfshow.vcproj
deleted file mode 100644
index 49a3f2b6..00000000
--- a/win32/mupdfshow.vcproj
+++ /dev/null
@@ -1,246 +0,0 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="8.00"
- Name="mupdfshow"
- ProjectGUID="{50644121-C85F-4EE9-9C54-F7D1BDFAE354}"
- RootNamespace="mupdf"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
- ConfigurationType="1"
- CharacterSet="2"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories="..\fitz;..\pdf"
- PreprocessorDefinitions="DEBUG=1"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- WarningLevel="3"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- GenerateDebugInformation="true"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
- ConfigurationType="1"
- CharacterSet="2"
- WholeProgramOptimization="1"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="2"
- EnableIntrinsicFunctions="true"
- AdditionalIncludeDirectories="..\fitz;..\pdf"
- RuntimeLibrary="0"
- EnableFunctionLevelLinking="true"
- WarningLevel="3"
- DebugInformationFormat="3"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- GenerateDebugInformation="true"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- <Configuration
- Name="Memento|Win32"
- OutputDirectory="$(ConfigurationName)"
- IntermediateDirectory="$(ConfigurationName)\$(ProjectName)"
- ConfigurationType="1"
- CharacterSet="2"
- >
- <Tool
- Name="VCPreBuildEventTool"
- />
- <Tool
- Name="VCCustomBuildTool"
- />
- <Tool
- Name="VCXMLDataGeneratorTool"
- />
- <Tool
- Name="VCWebServiceProxyGeneratorTool"
- />
- <Tool
- Name="VCMIDLTool"
- />
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- AdditionalIncludeDirectories="..\fitz;..\pdf"
- PreprocessorDefinitions="MEMENTO=1;DEBUG=1"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- WarningLevel="3"
- DebugInformationFormat="4"
- />
- <Tool
- Name="VCManagedResourceCompilerTool"
- />
- <Tool
- Name="VCResourceCompilerTool"
- />
- <Tool
- Name="VCPreLinkEventTool"
- />
- <Tool
- Name="VCLinkerTool"
- GenerateDebugInformation="true"
- TargetMachine="1"
- />
- <Tool
- Name="VCALinkTool"
- />
- <Tool
- Name="VCManifestTool"
- />
- <Tool
- Name="VCXDCMakeTool"
- />
- <Tool
- Name="VCBscMakeTool"
- />
- <Tool
- Name="VCFxCopTool"
- />
- <Tool
- Name="VCAppVerifierTool"
- />
- <Tool
- Name="VCWebDeploymentTool"
- />
- <Tool
- Name="VCPostBuildEventTool"
- />
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <File
- RelativePath="..\apps\mupdfshow.c"
- >
- </File>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
diff --git a/xps/xps_zip.c b/xps/xps_zip.c
index ff43abf2..bb6857ee 100644
--- a/xps/xps_zip.c
+++ b/xps/xps_zip.c
@@ -108,13 +108,11 @@ xps_read_zip_entry(xps_document *doc, xps_entry *ent, unsigned char *outbuf)
int code;
fz_context *ctx = doc->ctx;
- fz_lock(ctx, FZ_LOCK_FILE);
fz_seek(doc->file, ent->offset, 0);
sig = getlong(doc->file);
if (sig != ZIP_LOCAL_FILE_SIG)
{
- fz_unlock(ctx, FZ_LOCK_FILE);
fz_throw(doc->ctx, "wrong zip local file signature (0x%x)", sig);
}
@@ -137,7 +135,7 @@ xps_read_zip_entry(xps_document *doc, xps_entry *ent, unsigned char *outbuf)
}
else if (method == 8)
{
- inbuf = fz_malloc(doc->ctx, ent->csize);
+ inbuf = fz_malloc(ctx, ent->csize);
fz_read(doc->file, inbuf, ent->csize);
@@ -153,34 +151,29 @@ xps_read_zip_entry(xps_document *doc, xps_entry *ent, unsigned char *outbuf)
code = inflateInit2(&stream, -15);
if (code != Z_OK)
{
- fz_unlock(ctx, FZ_LOCK_FILE);
- fz_free(doc->ctx, inbuf);
- fz_throw(doc->ctx, "zlib inflateInit2 error: %s", stream.msg);
+ fz_free(ctx, inbuf);
+ fz_throw(ctx, "zlib inflateInit2 error: %s", stream.msg);
}
code = inflate(&stream, Z_FINISH);
if (code != Z_STREAM_END)
{
inflateEnd(&stream);
- fz_unlock(ctx, FZ_LOCK_FILE);
- fz_free(doc->ctx, inbuf);
- fz_throw(doc->ctx, "zlib inflate error: %s", stream.msg);
+ fz_free(ctx, inbuf);
+ fz_throw(ctx, "zlib inflate error: %s", stream.msg);
}
code = inflateEnd(&stream);
if (code != Z_OK)
{
- fz_unlock(ctx, FZ_LOCK_FILE);
- fz_free(doc->ctx, inbuf);
- fz_throw(doc->ctx, "zlib inflateEnd error: %s", stream.msg);
+ fz_free(ctx, inbuf);
+ fz_throw(ctx, "zlib inflateEnd error: %s", stream.msg);
}
- fz_free(doc->ctx, inbuf);
+ fz_free(ctx, inbuf);
}
else
{
- fz_unlock(ctx, FZ_LOCK_FILE);
- fz_throw(doc->ctx, "unknown compression method (%d)", method);
+ fz_throw(ctx, "unknown compression method (%d)", method);
}
- fz_unlock(ctx, FZ_LOCK_FILE);
}
/*
@@ -306,7 +299,6 @@ xps_find_and_read_zip_dir(xps_document *doc)
int i, n;
fz_context *ctx = doc->ctx;
- fz_lock(ctx, FZ_LOCK_FILE);
fz_seek(doc->file, 0, SEEK_END);
file_size = fz_tell(doc->file);
@@ -322,7 +314,6 @@ xps_find_and_read_zip_dir(xps_document *doc)
if (!memcmp(buf + i, "PK\5\6", 4))
{
xps_read_zip_dir(doc, file_size - back + i);
- fz_unlock(ctx, FZ_LOCK_FILE);
return;
}
}
@@ -330,8 +321,7 @@ xps_find_and_read_zip_dir(xps_document *doc)
back += sizeof buf - 4;
}
- fz_unlock(ctx, FZ_LOCK_FILE);
- fz_throw(doc->ctx, "cannot find end of central directory");
+ fz_throw(ctx, "cannot find end of central directory");
}
/*