summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gardiner <paulg.artifex@glidos.net>2012-08-29 10:58:09 +0100
committerPaul Gardiner <paulg.artifex@glidos.net>2012-08-29 10:58:09 +0100
commit6a5b8879b3b3b2a9ef085f38c1758d62456b921b (patch)
treef45fc1a9f32dcd31f335d27fffba75e4ceb9a23c
parentd85ad485bb64508bc59cfd4977cb5a37cf882070 (diff)
parent25552e9f2ec3f17a0ce1cbd8d7818170d132959a (diff)
downloadmupdf-6a5b8879b3b3b2a9ef085f38c1758d62456b921b.tar.xz
Merge branch 'master' into forms
Conflicts: cbz/mucbz.c pdf/pdf_parse.c pdf/pdf_form.c xps/xps_zip.c
-rw-r--r--android/AndroidManifest.xml2
-rw-r--r--android/jni/Core.mk13
-rw-r--r--android/jni/ThirdParty.mk183
-rw-r--r--android/res/layout/buttons.xml2
-rw-r--r--android/res/values/strings.xml1
-rw-r--r--android/src/com/artifex/mupdf/MuPDFActivity.java93
-rw-r--r--apps/mupdfinfo.c2
-rw-r--r--apps/pdfapp.c4
-rw-r--r--fitz/base_error.c2
-rw-r--r--fitz/crypt_sha2.c231
-rw-r--r--fitz/dev_trace.c86
-rw-r--r--fitz/filt_jbig2d.c15
-rw-r--r--fitz/fitz-internal.h43
-rw-r--r--fitz/fitz.h5
-rw-r--r--fitz/image_png.c18
-rw-r--r--fitz/memento.c172
-rw-r--r--fitz/memento.h41
-rw-r--r--fitz/res_font.c2
-rw-r--r--ios/Info.plist4
-rw-r--r--ios/MuPDF.xcodeproj/project.pbxproj8
-rw-r--r--ios/main.m127
-rw-r--r--ios/x_alt_blue.pngbin0 -> 344 bytes
-rw-r--r--ios/x_alt_blue@2x.pngbin0 -> 534 bytes
-rw-r--r--pdf/mupdf.h2
-rw-r--r--pdf/pdf_annot.c2
-rw-r--r--pdf/pdf_crypt.c125
-rw-r--r--pdf/pdf_form.c18
-rw-r--r--pdf/pdf_interpret.c15
-rw-r--r--pdf/pdf_nametree.c2
-rw-r--r--pdf/pdf_object.c8
-rw-r--r--pdf/pdf_parse.c12
-rw-r--r--pdf/pdf_write.c4
-rw-r--r--pdf/pdf_xobject.c8
33 files changed, 931 insertions, 319 deletions
diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml
index e69aeaf5..16e49f0e 100644
--- a/android/AndroidManifest.xml
+++ b/android/AndroidManifest.xml
@@ -2,7 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.artifex.mupdf"
android:versionCode="1"
- android:versionName="1.0">
+ android:versionName="1.1">
<supports-screens android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
diff --git a/android/jni/Core.mk b/android/jni/Core.mk
index cea16e74..69fcef49 100644
--- a/android/jni/Core.mk
+++ b/android/jni/Core.mk
@@ -4,14 +4,19 @@ include $(CLEAR_VARS)
MY_ROOT := ../..
+OPENJPEG := openjpeg-1.5.0-patched
+JPEG := jpeg-9
+ZLIB := zlib-1.2.7
+FREETYPE := freetype-2.4.10
+
LOCAL_CFLAGS += -DARCH_ARM -DARCH_THUMB -DARCH_ARM_CAN_LOAD_UNALIGNED
LOCAL_C_INCLUDES := \
../thirdparty/jbig2dec \
- ../thirdparty/openjpeg-1.5.0/libopenjpeg \
- ../thirdparty/jpeg-8d \
- ../thirdparty/zlib-1.2.5 \
- ../thirdparty/freetype-2.4.9/include \
+ ../thirdparty/$(OPENJPEG)/libopenjpeg \
+ ../thirdparty/$(JPEG) \
+ ../thirdparty/$(ZLIB) \
+ ../thirdparty/$(FREETYPE)/include \
../draw \
../fitz \
../pdf \
diff --git a/android/jni/ThirdParty.mk b/android/jni/ThirdParty.mk
index c80941d1..a2d05ccf 100644
--- a/android/jni/ThirdParty.mk
+++ b/android/jni/ThirdParty.mk
@@ -4,12 +4,17 @@ include $(CLEAR_VARS)
MY_ROOT := ../..
+OPENJPEG := openjpeg-1.5.0-patched
+JPEG := jpeg-9
+ZLIB := zlib-1.2.7
+FREETYPE := freetype-2.4.10
+
LOCAL_C_INCLUDES := \
../thirdparty/jbig2dec \
- ../thirdparty/openjpeg-1.5.0/libopenjpeg \
- ../thirdparty/jpeg-8d \
- ../thirdparty/zlib-1.2.5 \
- ../thirdparty/freetype-2.4.9/include \
+ ../thirdparty/$(OPENJPEG)/libopenjpeg \
+ ../thirdparty/$(JPEG) \
+ ../thirdparty/$(ZLIB) \
+ ../thirdparty/$(FREETYPE)/include \
../scripts
LOCAL_CFLAGS := \
@@ -34,90 +39,90 @@ LOCAL_SRC_FILES := \
$(MY_ROOT)/thirdparty/jbig2dec/jbig2_segment.c \
$(MY_ROOT)/thirdparty/jbig2dec/jbig2_symbol_dict.c \
$(MY_ROOT)/thirdparty/jbig2dec/jbig2_text.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/bio.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/cidx_manager.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/cio.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/dwt.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/event.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/image.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/j2k.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/j2k_lib.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/jp2.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/jpt.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/mct.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/mqc.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/openjpeg.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/phix_manager.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/pi.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/ppix_manager.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/raw.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/t1.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/t2.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/tcd.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/tgt.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/thix_manager.c \
- $(MY_ROOT)/thirdparty/openjpeg-1.5.0/libopenjpeg/tpix_manager.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jaricom.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jcomapi.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jdapimin.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jdapistd.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jdarith.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jdatadst.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jdatasrc.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jdcoefct.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jdcolor.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jddctmgr.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jdhuff.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jdinput.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jdmainct.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jdmarker.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jdmaster.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jdmerge.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jdpostct.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jdsample.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jdtrans.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jerror.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jfdctflt.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jfdctfst.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jfdctint.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jidctflt.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jidctfst.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jidctint.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jmemmgr.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jmemnobs.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jquant1.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jquant2.c \
- $(MY_ROOT)/thirdparty/jpeg-8d/jutils.c \
- $(MY_ROOT)/thirdparty/zlib-1.2.5/adler32.c \
- $(MY_ROOT)/thirdparty/zlib-1.2.5/compress.c \
- $(MY_ROOT)/thirdparty/zlib-1.2.5/crc32.c \
- $(MY_ROOT)/thirdparty/zlib-1.2.5/deflate.c \
- $(MY_ROOT)/thirdparty/zlib-1.2.5/inffast.c \
- $(MY_ROOT)/thirdparty/zlib-1.2.5/inflate.c \
- $(MY_ROOT)/thirdparty/zlib-1.2.5/inftrees.c \
- $(MY_ROOT)/thirdparty/zlib-1.2.5/trees.c \
- $(MY_ROOT)/thirdparty/zlib-1.2.5/uncompr.c \
- $(MY_ROOT)/thirdparty/zlib-1.2.5/zutil.c \
- $(MY_ROOT)/thirdparty/freetype-2.4.9/src/base/ftbase.c \
- $(MY_ROOT)/thirdparty/freetype-2.4.9/src/base/ftbbox.c \
- $(MY_ROOT)/thirdparty/freetype-2.4.9/src/base/ftbitmap.c \
- $(MY_ROOT)/thirdparty/freetype-2.4.9/src/base/ftgasp.c \
- $(MY_ROOT)/thirdparty/freetype-2.4.9/src/base/ftglyph.c \
- $(MY_ROOT)/thirdparty/freetype-2.4.9/src/base/ftinit.c \
- $(MY_ROOT)/thirdparty/freetype-2.4.9/src/base/ftstroke.c \
- $(MY_ROOT)/thirdparty/freetype-2.4.9/src/base/ftsynth.c \
- $(MY_ROOT)/thirdparty/freetype-2.4.9/src/base/ftsystem.c \
- $(MY_ROOT)/thirdparty/freetype-2.4.9/src/base/fttype1.c \
- $(MY_ROOT)/thirdparty/freetype-2.4.9/src/base/ftxf86.c \
- $(MY_ROOT)/thirdparty/freetype-2.4.9/src/cff/cff.c \
- $(MY_ROOT)/thirdparty/freetype-2.4.9/src/cid/type1cid.c \
- $(MY_ROOT)/thirdparty/freetype-2.4.9/src/psaux/psaux.c \
- $(MY_ROOT)/thirdparty/freetype-2.4.9/src/pshinter/pshinter.c \
- $(MY_ROOT)/thirdparty/freetype-2.4.9/src/psnames/psnames.c \
- $(MY_ROOT)/thirdparty/freetype-2.4.9/src/raster/raster.c \
- $(MY_ROOT)/thirdparty/freetype-2.4.9/src/smooth/smooth.c \
- $(MY_ROOT)/thirdparty/freetype-2.4.9/src/sfnt/sfnt.c \
- $(MY_ROOT)/thirdparty/freetype-2.4.9/src/truetype/truetype.c \
- $(MY_ROOT)/thirdparty/freetype-2.4.9/src/type1/type1.c
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/bio.c \
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/cidx_manager.c \
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/cio.c \
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/dwt.c \
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/event.c \
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/image.c \
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/j2k.c \
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/j2k_lib.c \
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/jp2.c \
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/jpt.c \
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/mct.c \
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/mqc.c \
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/openjpeg.c \
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/phix_manager.c \
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/pi.c \
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/ppix_manager.c \
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/raw.c \
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/t1.c \
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/t2.c \
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/tcd.c \
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/tgt.c \
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/thix_manager.c \
+ $(MY_ROOT)/thirdparty/$(OPENJPEG)/libopenjpeg/tpix_manager.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jaricom.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jcomapi.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jdapimin.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jdapistd.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jdarith.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jdatadst.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jdatasrc.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jdcoefct.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jdcolor.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jddctmgr.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jdhuff.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jdinput.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jdmainct.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jdmarker.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jdmaster.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jdmerge.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jdpostct.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jdsample.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jdtrans.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jerror.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jfdctflt.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jfdctfst.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jfdctint.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jidctflt.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jidctfst.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jidctint.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jmemmgr.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jmemnobs.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jquant1.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jquant2.c \
+ $(MY_ROOT)/thirdparty/$(JPEG)/jutils.c \
+ $(MY_ROOT)/thirdparty/$(ZLIB)/adler32.c \
+ $(MY_ROOT)/thirdparty/$(ZLIB)/compress.c \
+ $(MY_ROOT)/thirdparty/$(ZLIB)/crc32.c \
+ $(MY_ROOT)/thirdparty/$(ZLIB)/deflate.c \
+ $(MY_ROOT)/thirdparty/$(ZLIB)/inffast.c \
+ $(MY_ROOT)/thirdparty/$(ZLIB)/inflate.c \
+ $(MY_ROOT)/thirdparty/$(ZLIB)/inftrees.c \
+ $(MY_ROOT)/thirdparty/$(ZLIB)/trees.c \
+ $(MY_ROOT)/thirdparty/$(ZLIB)/uncompr.c \
+ $(MY_ROOT)/thirdparty/$(ZLIB)/zutil.c \
+ $(MY_ROOT)/thirdparty/$(FREETYPE)/src/base/ftbase.c \
+ $(MY_ROOT)/thirdparty/$(FREETYPE)/src/base/ftbbox.c \
+ $(MY_ROOT)/thirdparty/$(FREETYPE)/src/base/ftbitmap.c \
+ $(MY_ROOT)/thirdparty/$(FREETYPE)/src/base/ftgasp.c \
+ $(MY_ROOT)/thirdparty/$(FREETYPE)/src/base/ftglyph.c \
+ $(MY_ROOT)/thirdparty/$(FREETYPE)/src/base/ftinit.c \
+ $(MY_ROOT)/thirdparty/$(FREETYPE)/src/base/ftstroke.c \
+ $(MY_ROOT)/thirdparty/$(FREETYPE)/src/base/ftsynth.c \
+ $(MY_ROOT)/thirdparty/$(FREETYPE)/src/base/ftsystem.c \
+ $(MY_ROOT)/thirdparty/$(FREETYPE)/src/base/fttype1.c \
+ $(MY_ROOT)/thirdparty/$(FREETYPE)/src/base/ftxf86.c \
+ $(MY_ROOT)/thirdparty/$(FREETYPE)/src/cff/cff.c \
+ $(MY_ROOT)/thirdparty/$(FREETYPE)/src/cid/type1cid.c \
+ $(MY_ROOT)/thirdparty/$(FREETYPE)/src/psaux/psaux.c \
+ $(MY_ROOT)/thirdparty/$(FREETYPE)/src/pshinter/pshinter.c \
+ $(MY_ROOT)/thirdparty/$(FREETYPE)/src/psnames/psnames.c \
+ $(MY_ROOT)/thirdparty/$(FREETYPE)/src/raster/raster.c \
+ $(MY_ROOT)/thirdparty/$(FREETYPE)/src/smooth/smooth.c \
+ $(MY_ROOT)/thirdparty/$(FREETYPE)/src/sfnt/sfnt.c \
+ $(MY_ROOT)/thirdparty/$(FREETYPE)/src/truetype/truetype.c \
+ $(MY_ROOT)/thirdparty/$(FREETYPE)/src/type1/type1.c
include $(BUILD_STATIC_LIBRARY)
diff --git a/android/res/layout/buttons.xml b/android/res/layout/buttons.xml
index 641a6cef..a9f46d38 100644
--- a/android/res/layout/buttons.xml
+++ b/android/res/layout/buttons.xml
@@ -53,7 +53,7 @@
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
- android:layout_toLeftOf="@+id/searchButton"
+ android:layout_toLeftOf="@+id/outlineButton"
android:paddingLeft="15dp"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium" />
diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml
index 25a75b08..d61bb2aa 100644
--- a/android/res/values/strings.xml
+++ b/android/res/values/strings.xml
@@ -14,4 +14,5 @@
<string name="text_not_found">Text not found</string>
<string name="searching_">Searching...</string>
<string name="link_control">Link highlighting and enabling</string>
+ <string name="no_further_occurences_found">No further occurences found</string>
</resources>
diff --git a/android/src/com/artifex/mupdf/MuPDFActivity.java b/android/src/com/artifex/mupdf/MuPDFActivity.java
index 5696ea0b..c530b01b 100644
--- a/android/src/com/artifex/mupdf/MuPDFActivity.java
+++ b/android/src/com/artifex/mupdf/MuPDFActivity.java
@@ -16,6 +16,7 @@ import android.text.Editable;
import android.text.TextWatcher;
import android.text.method.PasswordTransformationMethod;
import android.view.KeyEvent;
+import android.view.Menu;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
@@ -82,6 +83,7 @@ public class MuPDFActivity extends Activity
private EditText mPasswordView;
private TextView mFilenameView;
private SeekBar mPageSlider;
+ private int mPageSliderRes;
private TextView mPageNumberView;
private ImageButton mSearchButton;
private ImageButton mCancelButton;
@@ -92,7 +94,7 @@ public class MuPDFActivity extends Activity
private ImageButton mSearchBack;
private ImageButton mSearchFwd;
private EditText mSearchText;
- private SafeAsyncTask<Integer,Integer,SearchTaskResult> mSearchTask;
+ private SafeAsyncTask<Void,Integer,SearchTaskResult> mSearchTask;
//private SearchTaskResult mSearchTaskResult;
private AlertDialog.Builder mAlertBuilder;
private LinkState mLinkState = LinkState.DEFAULT;
@@ -148,6 +150,7 @@ public class MuPDFActivity extends Activity
}
}
core = openFile(Uri.decode(uri.getEncodedPath()));
+ SearchTaskResult.set(null);
}
if (core != null && core.needsPassword()) {
requestPassword(savedInstanceState);
@@ -270,8 +273,8 @@ public class MuPDFActivity extends Activity
if (core == null)
return;
mPageNumberView.setText(String.format("%d/%d", i+1, core.countPages()));
- mPageSlider.setMax(core.countPages()-1);
- mPageSlider.setProgress(i);
+ mPageSlider.setMax((core.countPages()-1) * mPageSliderRes);
+ mPageSlider.setProgress(i * mPageSliderRes);
if (SearchTaskResult.get() != null && SearchTaskResult.get().pageNumber != i) {
SearchTaskResult.set(null);
mDocView.resetupChildren();
@@ -301,20 +304,24 @@ public class MuPDFActivity extends Activity
// controls in variables
makeButtonsView();
+ // Set up the page slider
+ int smax = Math.max(core.countPages()-1,1);
+ mPageSliderRes = ((10 + smax - 1)/smax) * 2;
+
// Set the file-name text
mFilenameView.setText(mFileName);
// Activate the seekbar
mPageSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
public void onStopTrackingTouch(SeekBar seekBar) {
- mDocView.setDisplayedViewIndex(seekBar.getProgress());
+ mDocView.setDisplayedViewIndex((seekBar.getProgress()+mPageSliderRes/2)/mPageSliderRes);
}
public void onStartTrackingTouch(SeekBar seekBar) {}
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
- updatePageNumView(progress);
+ updatePageNumView((progress+mPageSliderRes/2)/mPageSliderRes);
}
});
@@ -511,8 +518,8 @@ public class MuPDFActivity extends Activity
// Update page number text and slider
int index = mDocView.getDisplayedViewIndex();
updatePageNumView(index);
- mPageSlider.setMax(core.countPages()-1);
- mPageSlider.setProgress(index);
+ mPageSlider.setMax((core.countPages()-1)*mPageSliderRes);
+ mPageSlider.setProgress(index*mPageSliderRes);
if (mTopBarIsSearch) {
mSearchText.requestFocus();
showKeyboard();
@@ -576,21 +583,25 @@ public class MuPDFActivity extends Activity
}
void searchModeOn() {
- mTopBarIsSearch = true;
- //Focus on EditTextWidget
- mSearchText.requestFocus();
- showKeyboard();
- mTopBarSwitcher.showNext();
+ if (!mTopBarIsSearch) {
+ mTopBarIsSearch = true;
+ //Focus on EditTextWidget
+ mSearchText.requestFocus();
+ showKeyboard();
+ mTopBarSwitcher.showNext();
+ }
}
void searchModeOff() {
- mTopBarIsSearch = false;
- hideKeyboard();
- mTopBarSwitcher.showPrevious();
- SearchTaskResult.set(null);
- // Make the ReaderView act on the change to mSearchTaskResult
- // via overridden onChildSetup method.
- mDocView.resetupChildren();
+ if (mTopBarIsSearch) {
+ mTopBarIsSearch = false;
+ hideKeyboard();
+ mTopBarSwitcher.showPrevious();
+ SearchTaskResult.set(null);
+ // Make the ReaderView act on the change to mSearchTaskResult
+ // via overridden onChildSetup method.
+ mDocView.resetupChildren();
+ }
}
void updatePageNumView(int index) {
@@ -642,6 +653,9 @@ public class MuPDFActivity extends Activity
return;
killSearch();
+ final int increment = direction;
+ final int startIndex = SearchTaskResult.get() == null ? mDocView.getDisplayedViewIndex() : SearchTaskResult.get().pageNumber + increment;
+
final ProgressDialogX progressDialog = new ProgressDialogX(this);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setTitle(getString(R.string.searching_));
@@ -652,14 +666,10 @@ public class MuPDFActivity extends Activity
});
progressDialog.setMax(core.countPages());
- mSearchTask = new SafeAsyncTask<Integer,Integer,SearchTaskResult>() {
+ mSearchTask = new SafeAsyncTask<Void,Integer,SearchTaskResult>() {
@Override
- protected SearchTaskResult doInBackground(Integer... params) {
- int index;
- if (SearchTaskResult.get() == null)
- index = mDocView.getDisplayedViewIndex();
- else
- index = SearchTaskResult.get().pageNumber + params[0].intValue();
+ protected SearchTaskResult doInBackground(Void... params) {
+ int index = startIndex;
while (0 <= index && index < core.countPages() && !isCancelled()) {
publishProgress(index);
@@ -668,7 +678,7 @@ public class MuPDFActivity extends Activity
if (searchHits != null && searchHits.length > 0)
return new SearchTaskResult(mSearchText.getText().toString(), index, searchHits);
- index += params[0].intValue();
+ index += increment;
}
return null;
}
@@ -684,7 +694,7 @@ public class MuPDFActivity extends Activity
// via overridden onChildSetup method.
mDocView.resetupChildren();
} else {
- mAlertBuilder.setTitle(R.string.text_not_found);
+ mAlertBuilder.setTitle(SearchTaskResult.get() == null ? R.string.text_not_found : R.string.no_further_occurences_found);
AlertDialog alert = mAlertBuilder.create();
alert.setButton(AlertDialog.BUTTON_POSITIVE, "Dismiss",
(DialogInterface.OnClickListener)null);
@@ -710,12 +720,37 @@ public class MuPDFActivity extends Activity
mHandler.postDelayed(new Runnable() {
public void run() {
if (!progressDialog.isCancelled())
+ {
progressDialog.show();
+ progressDialog.setProgress(startIndex);
+ }
}
}, SEARCH_PROGRESS_DELAY);
}
};
- mSearchTask.safeExecute(new Integer(direction));
+ mSearchTask.safeExecute();
+ }
+
+ @Override
+ public boolean onSearchRequested() {
+ if (mButtonsVisible && mTopBarIsSearch) {
+ hideButtons();
+ } else {
+ showButtons();
+ searchModeOn();
+ }
+ return super.onSearchRequested();
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ if (mButtonsVisible && !mTopBarIsSearch) {
+ hideButtons();
+ } else {
+ showButtons();
+ searchModeOff();
+ }
+ return super.onPrepareOptionsMenu(menu);
}
}
diff --git a/apps/mupdfinfo.c b/apps/mupdfinfo.c
index 279298c2..6c0a31d7 100644
--- a/apps/mupdfinfo.c
+++ b/apps/mupdfinfo.c
@@ -901,7 +901,7 @@ showinfo(char *filename, int show, char *pagelist)
pagecount = pdf_count_pages(xref);
spec = fz_strsep(&pagelist, ",");
- while (spec)
+ while (spec && pagecount)
{
dash = strchr(spec, '-');
diff --git a/apps/pdfapp.c b/apps/pdfapp.c
index d4d292da..b95b4178 100644
--- a/apps/pdfapp.c
+++ b/apps/pdfapp.c
@@ -42,7 +42,7 @@ static void pdfapp_error(pdfapp_t *app, char *msg)
char *pdfapp_version(pdfapp_t *app)
{
return
- "MuPDF 1.0\n"
+ "MuPDF 1.1\n"
"Copyright 2006-2012 Artifex Software, Inc.\n";
}
@@ -117,7 +117,7 @@ void pdfapp_open(pdfapp_t *app, char *filename, int reload)
{
password = winpassword(app, filename);
if (!password)
- pdfapp_error(app, "Needs a password.");
+ fz_throw(ctx, "Needs a password");
okay = fz_authenticate_password(app->doc, password);
if (!okay)
pdfapp_warn(app, "Invalid password.");
diff --git a/fitz/base_error.c b/fitz/base_error.c
index ce048a1e..995f59c6 100644
--- a/fitz/base_error.c
+++ b/fitz/base_error.c
@@ -4,7 +4,7 @@
void fz_var_imp(void *var)
{
- var = var; /* Do nothing */
+ UNUSED(var); /* Do nothing */
}
void fz_flush_warnings(fz_context *ctx)
diff --git a/fitz/crypt_sha2.c b/fitz/crypt_sha2.c
index 64284cfa..8d6dcbe1 100644
--- a/fitz/crypt_sha2.c
+++ b/fitz/crypt_sha2.c
@@ -5,6 +5,8 @@ The code was modified a little to fit into liblzma and fitz.
This file has been put into the public domain.
You can do whatever you want with this file.
+
+SHA-384 and SHA-512 were also taken from Crypto++ and adapted for fitz.
*/
#include "fitz-internal.h"
@@ -27,8 +29,24 @@ static inline unsigned int bswap32(unsigned int num)
return num;
}
+static inline uint64_t bswap64(uint64_t num)
+{
+ if (!isbigendian())
+ {
+ return ( (((num) << 56))
+ | (((num) << 40) & 0x00FF000000000000ULL)
+ | (((num) << 24) & 0x0000FF0000000000ULL)
+ | (((num) << 8) & 0x000000FF00000000ULL)
+ | (((num) >> 8) & 0x00000000FF000000ULL)
+ | (((num) >> 24) & 0x0000000000FF0000ULL)
+ | (((num) >> 40) & 0x000000000000FF00ULL)
+ | (((num) >> 56)) );
+ }
+ return num;
+}
+
/* At least on x86, GCC is able to optimize this to a rotate instruction. */
-#define rotr_32(num, amount) ((num) >> (amount) | (num) << (32 - (amount)))
+#define rotr(num, amount) ((num) >> (amount) | (num) << (8 * sizeof(num) - (amount)))
#define blk0(i) (W[i] = data[i])
#define blk2(i) (W[i & 15] += s1(W[(i - 2) & 15]) + W[(i - 7) & 15] \
@@ -47,15 +65,17 @@ static inline unsigned int bswap32(unsigned int num)
#define h(i) T[(7 - i) & 7]
#define R(i) \
- h(i) += S1(e(i)) + Ch(e(i), f(i), g(i)) + SHA256_K[i + j] \
+ h(i) += S1(e(i)) + Ch(e(i), f(i), g(i)) + K[i + j] \
+ (j ? blk2(i) : blk0(i)); \
d(i) += h(i); \
h(i) += S0(a(i)) + Maj(a(i), b(i), c(i))
-#define S0(x) (rotr_32(x, 2) ^ rotr_32(x, 13) ^ rotr_32(x, 22))
-#define S1(x) (rotr_32(x, 6) ^ rotr_32(x, 11) ^ rotr_32(x, 25))
-#define s0(x) (rotr_32(x, 7) ^ rotr_32(x, 18) ^ (x >> 3))
-#define s1(x) (rotr_32(x, 17) ^ rotr_32(x, 19) ^ (x >> 10))
+/* For SHA256 */
+
+#define S0(x) (rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22))
+#define S1(x) (rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25))
+#define s0(x) (rotr(x, 7) ^ rotr(x, 18) ^ (x >> 3))
+#define s1(x) (rotr(x, 17) ^ rotr(x, 19) ^ (x >> 10))
static const unsigned int SHA256_K[64] = {
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
@@ -77,8 +97,9 @@ static const unsigned int SHA256_K[64] = {
};
static void
-transform(unsigned int state[8], const unsigned int data_xe[16])
+transform256(unsigned int state[8], const unsigned int data_xe[16])
{
+ const unsigned int *K = SHA256_K;
unsigned int data[16];
unsigned int W[16];
unsigned int T[8];
@@ -110,6 +131,11 @@ transform(unsigned int state[8], const unsigned int data_xe[16])
state[7] += h(0);
}
+#undef S0
+#undef S1
+#undef s0
+#undef s1
+
void fz_sha256_init(fz_sha256 *context)
{
context->count[0] = context->count[1] = 0;
@@ -147,7 +173,7 @@ void fz_sha256_update(fz_sha256 *context, const unsigned char *input, unsigned i
context->count[1]++;
if ((context->count[0] & 0x3F) == 0)
- transform(context->state, context->buffer.u32);
+ transform256(context->state, context->buffer.u32);
}
}
@@ -162,7 +188,7 @@ void fz_sha256_final(fz_sha256 *context, unsigned char digest[32])
{
if (j == 64)
{
- transform(context->state, context->buffer.u32);
+ transform256(context->state, context->buffer.u32);
j = 0;
}
context->buffer.u8[j++] = 0x00;
@@ -174,9 +200,194 @@ void fz_sha256_final(fz_sha256 *context, unsigned char digest[32])
context->buffer.u32[14] = bswap32(context->count[1]);
context->buffer.u32[15] = bswap32(context->count[0]);
- transform(context->state, context->buffer.u32);
+ transform256(context->state, context->buffer.u32);
for (j = 0; j < 8; j++)
((unsigned int *)digest)[j] = bswap32(context->state[j]);
memset(context, 0, sizeof(fz_sha256));
}
+
+/* For SHA512 */
+
+#define S0(x) (rotr(x, 28) ^ rotr(x, 34) ^ rotr(x, 39))
+#define S1(x) (rotr(x, 14) ^ rotr(x, 18) ^ rotr(x, 41))
+#define s0(x) (rotr(x, 1) ^ rotr(x, 8) ^ (x >> 7))
+#define s1(x) (rotr(x, 19) ^ rotr(x, 61) ^ (x >> 6))
+
+static const uint64_t SHA512_K[80] = {
+ 0x428A2F98D728AE22ULL, 0x7137449123EF65CDULL,
+ 0xB5C0FBCFEC4D3B2FULL, 0xE9B5DBA58189DBBCULL,
+ 0x3956C25BF348B538ULL, 0x59F111F1B605D019ULL,
+ 0x923F82A4AF194F9BULL, 0xAB1C5ED5DA6D8118ULL,
+ 0xD807AA98A3030242ULL, 0x12835B0145706FBEULL,
+ 0x243185BE4EE4B28CULL, 0x550C7DC3D5FFB4E2ULL,
+ 0x72BE5D74F27B896FULL, 0x80DEB1FE3B1696B1ULL,
+ 0x9BDC06A725C71235ULL, 0xC19BF174CF692694ULL,
+ 0xE49B69C19EF14AD2ULL, 0xEFBE4786384F25E3ULL,
+ 0x0FC19DC68B8CD5B5ULL, 0x240CA1CC77AC9C65ULL,
+ 0x2DE92C6F592B0275ULL, 0x4A7484AA6EA6E483ULL,
+ 0x5CB0A9DCBD41FBD4ULL, 0x76F988DA831153B5ULL,
+ 0x983E5152EE66DFABULL, 0xA831C66D2DB43210ULL,
+ 0xB00327C898FB213FULL, 0xBF597FC7BEEF0EE4ULL,
+ 0xC6E00BF33DA88FC2ULL, 0xD5A79147930AA725ULL,
+ 0x06CA6351E003826FULL, 0x142929670A0E6E70ULL,
+ 0x27B70A8546D22FFCULL, 0x2E1B21385C26C926ULL,
+ 0x4D2C6DFC5AC42AEDULL, 0x53380D139D95B3DFULL,
+ 0x650A73548BAF63DEULL, 0x766A0ABB3C77B2A8ULL,
+ 0x81C2C92E47EDAEE6ULL, 0x92722C851482353BULL,
+ 0xA2BFE8A14CF10364ULL, 0xA81A664BBC423001ULL,
+ 0xC24B8B70D0F89791ULL, 0xC76C51A30654BE30ULL,
+ 0xD192E819D6EF5218ULL, 0xD69906245565A910ULL,
+ 0xF40E35855771202AULL, 0x106AA07032BBD1B8ULL,
+ 0x19A4C116B8D2D0C8ULL, 0x1E376C085141AB53ULL,
+ 0x2748774CDF8EEB99ULL, 0x34B0BCB5E19B48A8ULL,
+ 0x391C0CB3C5C95A63ULL, 0x4ED8AA4AE3418ACBULL,
+ 0x5B9CCA4F7763E373ULL, 0x682E6FF3D6B2B8A3ULL,
+ 0x748F82EE5DEFB2FCULL, 0x78A5636F43172F60ULL,
+ 0x84C87814A1F0AB72ULL, 0x8CC702081A6439ECULL,
+ 0x90BEFFFA23631E28ULL, 0xA4506CEBDE82BDE9ULL,
+ 0xBEF9A3F7B2C67915ULL, 0xC67178F2E372532BULL,
+ 0xCA273ECEEA26619CULL, 0xD186B8C721C0C207ULL,
+ 0xEADA7DD6CDE0EB1EULL, 0xF57D4F7FEE6ED178ULL,
+ 0x06F067AA72176FBAULL, 0x0A637DC5A2C898A6ULL,
+ 0x113F9804BEF90DAEULL, 0x1B710B35131C471BULL,
+ 0x28DB77F523047D84ULL, 0x32CAAB7B40C72493ULL,
+ 0x3C9EBE0A15C9BEBCULL, 0x431D67C49C100D4CULL,
+ 0x4CC5D4BECB3E42B6ULL, 0x597F299CFC657E2AULL,
+ 0x5FCB6FAB3AD6FAECULL, 0x6C44198C4A475817ULL,
+};
+
+static void
+transform512(uint64_t state[8], const uint64_t data_xe[16])
+{
+ const uint64_t *K = SHA512_K;
+ uint64_t data[16];
+ uint64_t W[16];
+ uint64_t T[8];
+ unsigned int j;
+
+ /* ensure big-endian integers */
+ for (j = 0; j < 16; j++)
+ data[j] = bswap64(data_xe[j]);
+
+ /* Copy state[] to working vars. */
+ memcpy(T, state, sizeof(T));
+
+ /* 80 operations, partially loop unrolled */
+ for (j = 0; j < 80; j+= 16) {
+ R( 0); R( 1); R( 2); R( 3);
+ R( 4); R( 5); R( 6); R( 7);
+ R( 8); R( 9); R(10); R(11);
+ R(12); R(13); R(14); R(15);
+ }
+
+ /* Add the working vars back into state[]. */
+ state[0] += a(0);
+ state[1] += b(0);
+ state[2] += c(0);
+ state[3] += d(0);
+ state[4] += e(0);
+ state[5] += f(0);
+ state[6] += g(0);
+ state[7] += h(0);
+}
+
+#undef S0
+#undef S1
+#undef s0
+#undef s1
+
+void fz_sha512_init(fz_sha512 *context)
+{
+ context->count[0] = context->count[1] = 0;
+
+ context->state[0] = 0x6A09E667F3BCC908ull;
+ context->state[1] = 0xBB67AE8584CAA73Bull;
+ context->state[2] = 0x3C6EF372FE94F82Bull;
+ context->state[3] = 0xA54FF53A5F1D36F1ull;
+ context->state[4] = 0x510E527FADE682D1ull;
+ context->state[5] = 0x9B05688C2B3E6C1Full;
+ context->state[6] = 0x1F83D9ABFB41BD6Bull;
+ context->state[7] = 0x5BE0CD19137E2179ull;
+}
+
+void fz_sha512_update(fz_sha512 *context, const unsigned char *input, unsigned int inlen)
+{
+ /* Copy the input data into a properly aligned temporary buffer.
+ * This way we can be called with arbitrarily sized buffers
+ * (no need to be multiple of 128 bytes), and the code works also
+ * on architectures that don't allow unaligned memory access. */
+ while (inlen > 0)
+ {
+ const unsigned int copy_start = context->count[0] & 0x7F;
+ unsigned int copy_size = 128 - copy_start;
+ if (copy_size > inlen)
+ copy_size = inlen;
+
+ memcpy(context->buffer.u8 + copy_start, input, copy_size);
+
+ input += copy_size;
+ inlen -= copy_size;
+ context->count[0] += copy_size;
+ /* carry overflow from low to high */
+ if (context->count[0] < copy_size)
+ context->count[1]++;
+
+ if ((context->count[0] & 0x7F) == 0)
+ transform512(context->state, context->buffer.u64);
+ }
+}
+
+void fz_sha512_final(fz_sha512 *context, unsigned char digest[128])
+{
+ /* Add padding as described in RFC 3174 (it describes SHA-1 but
+ * the same padding style is used for SHA-512 too). */
+ unsigned int j = context->count[0] & 0x7F;
+ context->buffer.u8[j++] = 0x80;
+
+ while (j != 120)
+ {
+ if (j == 128)
+ {
+ transform512(context->state, context->buffer.u64);
+ j = 0;
+ }
+ context->buffer.u8[j++] = 0x00;
+ }
+
+ /* Convert the message size from bytes to bits. */
+ context->count[1] = (context->count[1] << 3) + (context->count[0] >> 29);
+ context->count[0] = context->count[0] << 3;
+
+ context->buffer.u64[14] = bswap64(context->count[1]);
+ context->buffer.u64[15] = bswap64(context->count[0]);
+ transform512(context->state, context->buffer.u64);
+
+ for (j = 0; j < 16; j++)
+ ((uint64_t *)digest)[j] = bswap64(context->state[j]);
+ memset(context, 0, sizeof(fz_sha512));
+}
+
+void fz_sha384_init(fz_sha384 *context)
+{
+ context->count[0] = context->count[1] = 0;
+
+ context->state[0] = 0xCBBB9D5DC1059ED8ull;
+ context->state[1] = 0x629A292A367CD507ull;
+ context->state[2] = 0x9159015A3070DD17ull;
+ context->state[3] = 0x152FECD8F70E5939ull;
+ context->state[4] = 0x67332667FFC00B31ull;
+ context->state[5] = 0x8EB44A8768581511ull;
+ context->state[6] = 0xDB0C2E0D64F98FA7ull;
+ context->state[7] = 0x47B5481DBEFA4FA4ull;
+}
+
+void fz_sha384_update(fz_sha384 *context, const unsigned char *input, unsigned int inlen)
+{
+ fz_sha512_update(context, input, inlen);
+}
+
+void fz_sha384_final(fz_sha384 *context, unsigned char digest[48])
+{
+ fz_sha512_final(context, digest);
+}
diff --git a/fitz/dev_trace.c b/fitz/dev_trace.c
index b3c73ff2..514ee780 100644
--- a/fitz/dev_trace.c
+++ b/fitz/dev_trace.c
@@ -3,14 +3,14 @@
static void
fz_trace_matrix(fz_matrix ctm)
{
- printf("matrix=\"%g %g %g %g %g %g\" ",
+ printf(" matrix=\"%g %g %g %g %g %g\"",
ctm.a, ctm.b, ctm.c, ctm.d, ctm.e, ctm.f);
}
static void
fz_trace_trm(fz_matrix trm)
{
- printf("trm=\"%g %g %g %g\" ",
+ printf(" trm=\"%g %g %g %g\"",
trm.a, trm.b, trm.c, trm.d);
}
@@ -18,12 +18,12 @@ static void
fz_trace_color(fz_colorspace *colorspace, float *color, float alpha)
{
int i;
- printf("colorspace=\"%s\" color=\"", colorspace->name);
+ printf(" colorspace=\"%s\" color=\"", colorspace->name);
for (i = 0; i < colorspace->n; i++)
printf("%s%g", i == 0 ? "" : " ", color[i]);
- printf("\" ");
+ printf("\"");
if (alpha < 1)
- printf("alpha=\"%g\" ", alpha);
+ printf(" alpha=\"%g\"", alpha);
}
static void
@@ -41,26 +41,26 @@ fz_trace_path(fz_path *path, int indent)
case FZ_MOVETO:
x = path->items[i++].v;
y = path->items[i++].v;
- printf("<moveto x=\"%g\" y=\"%g\" />\n", x, y);
+ printf("<moveto x=\"%g\" y=\"%g\"/>\n", x, y);
break;
case FZ_LINETO:
x = path->items[i++].v;
y = path->items[i++].v;
- printf("<lineto x=\"%g\" y=\"%g\" />\n", x, y);
+ printf("<lineto x=\"%g\" y=\"%g\"/>\n", x, y);
break;
case FZ_CURVETO:
x = path->items[i++].v;
y = path->items[i++].v;
- printf("<curveto x1=\"%g\" y1=\"%g\" ", x, y);
+ printf("<curveto x1=\"%g\" y1=\"%g\"", x, y);
x = path->items[i++].v;
y = path->items[i++].v;
- printf("x2=\"%g\" y2=\"%g\" ", x, y);
+ printf(" x2=\"%g\" y2=\"%g\"", x, y);
x = path->items[i++].v;
y = path->items[i++].v;
- printf("x3=\"%g\" y3=\"%g\" />\n", x, y);
+ printf(" x3=\"%g\" y3=\"%g\"/>\n", x, y);
break;
case FZ_CLOSE_PATH:
- printf("<closepath />\n");
+ printf("<closepath/>\n");
break;
}
}
@@ -70,11 +70,11 @@ static void
fz_trace_fill_path(fz_device *dev, fz_path *path, int even_odd, fz_matrix ctm,
fz_colorspace *colorspace, float *color, float alpha)
{
- printf("<fill_path ");
+ printf("<fill_path");
if (even_odd)
- printf("winding=\"eofill\" ");
+ printf(" winding=\"eofill\"");
else
- printf("winding=\"nonzero\" ");
+ printf(" winding=\"nonzero\"");
fz_trace_color(colorspace, color, alpha);
fz_trace_matrix(ctm);
printf(">\n");
@@ -88,17 +88,17 @@ fz_trace_stroke_path(fz_device *dev, fz_path *path, fz_stroke_state *stroke, fz_
{
int i;
- printf("<stroke_path ");
- printf("linewidth=\"%g\" ", stroke->linewidth);
- printf("miterlimit=\"%g\" ", stroke->miterlimit);
- printf("linecap=\"%d,%d,%d\" ", stroke->start_cap, stroke->dash_cap, stroke->end_cap);
- printf("linejoin=\"%d\" ", stroke->linejoin);
+ printf("<stroke_path");
+ printf(" linewidth=\"%g\"", stroke->linewidth);
+ printf(" miterlimit=\"%g\"", stroke->miterlimit);
+ printf(" linecap=\"%d,%d,%d\"", stroke->start_cap, stroke->dash_cap, stroke->end_cap);
+ printf(" linejoin=\"%d\"", stroke->linejoin);
if (stroke->dash_len)
{
- printf("dash_phase=\"%g\" dash=\"", stroke->dash_phase);
+ printf(" dash_phase=\"%g\" dash=\"", stroke->dash_phase);
for (i = 0; i < stroke->dash_len; i++)
- printf("%g ", stroke->dash_list[i]);
+ printf("%s%g", i > 0 ? " " : "", stroke->dash_list[i]);
printf("\"");
}
@@ -116,12 +116,11 @@ fz_trace_clip_path(fz_device *dev, fz_path *path, fz_rect *rect, int even_odd, f
{
printf("<clip_path ");
if (even_odd)
- printf("winding=\"eofill\" ");
+ printf(" winding=\"eofill\"");
else
- printf("winding=\"nonzero\" ");
+ printf(" winding=\"nonzero\"");
fz_trace_matrix(ctm);
- printf("contentbbox=\"%g %g %g %g\">\n",
- rect->x0, rect->y0, rect->x1, rect->y1);
+ printf(" contentbbox=\"%g %g %g %g\">\n", rect->x0, rect->y0, rect->x1, rect->y1);
fz_trace_path(path, 0);
printf("</clip_path>\n");
}
@@ -129,7 +128,7 @@ fz_trace_clip_path(fz_device *dev, fz_path *path, fz_rect *rect, int even_odd, f
static void
fz_trace_clip_stroke_path(fz_device *dev, fz_path *path, fz_rect *rect, fz_stroke_state *stroke, fz_matrix ctm)
{
- printf("<clip_stroke_path ");
+ printf("<clip_stroke_path");
fz_trace_matrix(ctm);
printf(">\n");
fz_trace_path(path, 0);
@@ -140,7 +139,7 @@ static void
fz_trace_fill_text(fz_device *dev, fz_text *text, fz_matrix ctm,
fz_colorspace *colorspace, float *color, float alpha)
{
- printf("<fill_text font=\"%s\" wmode=\"%d\" ", text->font->name, text->wmode);
+ printf("<fill_text font=\"%s\" wmode=\"%d\"", text->font->name, text->wmode);
fz_trace_color(colorspace, color, alpha);
fz_trace_matrix(ctm);
fz_trace_trm(text->trm);
@@ -153,7 +152,7 @@ static void
fz_trace_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm,
fz_colorspace *colorspace, float *color, float alpha)
{
- printf("<stroke_text font=\"%s\" wmode=\"%d\" ", text->font->name, text->wmode);
+ printf("<stroke_text font=\"%s\" wmode=\"%d\"", text->font->name, text->wmode);
fz_trace_color(colorspace, color, alpha);
fz_trace_matrix(ctm);
fz_trace_trm(text->trm);
@@ -165,8 +164,8 @@ fz_trace_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_
static void
fz_trace_clip_text(fz_device *dev, fz_text *text, fz_matrix ctm, int accumulate)
{
- printf("<clip_text font=\"%s\" wmode=\"%d\" ", text->font->name, text->wmode);
- printf("accumulate=\"%d\" ", accumulate);
+ printf("<clip_text font=\"%s\" wmode=\"%d\"", text->font->name, text->wmode);
+ printf(" accumulate=\"%d\"", accumulate);
fz_trace_matrix(ctm);
fz_trace_trm(text->trm);
printf(">\n");
@@ -177,7 +176,7 @@ fz_trace_clip_text(fz_device *dev, fz_text *text, fz_matrix ctm, int accumulate)
static void
fz_trace_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm)
{
- printf("<clip_stroke_text font=\"%s\" wmode=\"%d\" ", text->font->name, text->wmode);
+ printf("<clip_stroke_text font=\"%s\" wmode=\"%d\"", text->font->name, text->wmode);
fz_trace_matrix(ctm);
fz_trace_trm(text->trm);
printf(">\n");
@@ -188,7 +187,7 @@ fz_trace_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke
static void
fz_trace_ignore_text(fz_device *dev, fz_text *text, fz_matrix ctm)
{
- printf("<ignore_text font=\"%s\" wmode=\"%d\" ", text->font->name, text->wmode);
+ printf("<ignore_text font=\"%s\" wmode=\"%d\"", text->font->name, text->wmode);
fz_trace_matrix(ctm);
fz_trace_trm(text->trm);
printf(">\n");
@@ -199,15 +198,16 @@ fz_trace_ignore_text(fz_device *dev, fz_text *text, fz_matrix ctm)
static void
fz_trace_fill_image(fz_device *dev, fz_image *image, fz_matrix ctm, float alpha)
{
- printf("<fill_image alpha=\"%g\" ", alpha);
+ printf("<fill_image alpha=\"%g\"", alpha);
fz_trace_matrix(ctm);
+ printf(" width=\"%d\" height=\"%d\"", image->w, image->h);
printf("/>\n");
}
static void
fz_trace_fill_shade(fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha)
{
- printf("<fill_shade alpha=\"%g\" ", alpha);
+ printf("<fill_shade alpha=\"%g\"", alpha);
fz_trace_matrix(ctm);
printf("/>\n");
}
@@ -216,30 +216,32 @@ static void
fz_trace_fill_image_mask(fz_device *dev, fz_image *image, fz_matrix ctm,
fz_colorspace *colorspace, float *color, float alpha)
{
- printf("<fill_image_mask ");
+ printf("<fill_image_mask");
fz_trace_matrix(ctm);
fz_trace_color(colorspace, color, alpha);
+ printf(" width=\"%d\" height=\"%d\"", image->w, image->h);
printf("/>\n");
}
static void
fz_trace_clip_image_mask(fz_device *dev, fz_image *image, fz_rect *rect, fz_matrix ctm)
{
- printf("<clip_image_mask ");
+ printf("<clip_image_mask");
fz_trace_matrix(ctm);
+ printf(" width=\"%d\" height=\"%d\"", image->w, image->h);
printf("/>\n");
}
static void
fz_trace_pop_clip(fz_device *dev)
{
- printf("<pop_clip />\n");
+ printf("<pop_clip/>\n");
}
static void
fz_trace_begin_mask(fz_device *dev, fz_rect bbox, int luminosity, fz_colorspace *colorspace, float *color)
{
- printf("<mask bbox=\"%g %g %g %g\" s=\"%s\" ",
+ printf("<mask bbox=\"%g %g %g %g\" s=\"%s\"",
bbox.x0, bbox.y0, bbox.x1, bbox.y1,
luminosity ? "luminosity" : "alpha");
printf(">\n");
@@ -268,10 +270,10 @@ fz_trace_end_group(fz_device *dev)
static void
fz_trace_begin_tile(fz_device *dev, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm)
{
- printf("<tile ");
- printf("area=\"%g %g %g %g\" ", area.x0, area.y0, area.x1, area.y1);
- printf("view=\"%g %g %g %g\" ", view.x0, view.y0, view.x1, view.y1);
- printf("xstep=\"%g\" ystep=\"%g\" ", xstep, ystep);
+ printf("<tile");
+ printf(" area=\"%g %g %g %g\"", area.x0, area.y0, area.x1, area.y1);
+ printf(" view=\"%g %g %g %g\"", view.x0, view.y0, view.x1, view.y1);
+ printf(" xstep=\"%g\" ystep=\"%g\"", xstep, ystep);
fz_trace_matrix(ctm);
printf(">\n");
}
diff --git a/fitz/filt_jbig2d.c b/fitz/filt_jbig2d.c
index 415534c0..d7f09cee 100644
--- a/fitz/filt_jbig2d.c
+++ b/fitz/filt_jbig2d.c
@@ -1,20 +1,5 @@
#include "fitz-internal.h"
-#ifdef _WIN32 /* Microsoft Visual C++ */
-
-typedef signed char int8_t;
-typedef short int int16_t;
-typedef int int32_t;
-typedef __int64 int64_t;
-
-typedef unsigned char uint8_t;
-typedef unsigned short int uint16_t;
-typedef unsigned int uint32_t;
-
-#else
-#include <inttypes.h>
-#endif
-
#include <jbig2.h>
typedef struct fz_jbig2d_s fz_jbig2d;
diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h
index 02d452f4..1d641817 100644
--- a/fitz/fitz-internal.h
+++ b/fitz/fitz-internal.h
@@ -3,13 +3,28 @@
#include "fitz.h"
+#ifdef _WIN32 /* Microsoft Visual C++ */
+
+typedef signed char int8_t;
+typedef short int int16_t;
+typedef int int32_t;
+typedef __int64 int64_t;
+
+typedef unsigned char uint8_t;
+typedef unsigned short int uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned __int64 uint64_t;
+
+#else
+#include <inttypes.h>
+#endif
+
struct fz_warn_context_s
{
char message[256];
int count;
};
-
fz_context *fz_clone_context_internal(fz_context *ctx);
void fz_new_aa_context(fz_context *ctx);
@@ -156,6 +171,32 @@ void fz_sha256_init(fz_sha256 *state);
void fz_sha256_update(fz_sha256 *state, const unsigned char *input, unsigned int inlen);
void fz_sha256_final(fz_sha256 *state, unsigned char digest[32]);
+/* sha-512 digests */
+
+typedef struct fz_sha512_s fz_sha512;
+
+struct fz_sha512_s
+{
+ uint64_t state[8];
+ unsigned int count[2];
+ union {
+ unsigned char u8[128];
+ uint64_t u64[16];
+ } buffer;
+};
+
+void fz_sha512_init(fz_sha512 *state);
+void fz_sha512_update(fz_sha512 *state, const unsigned char *input, unsigned int inlen);
+void fz_sha512_final(fz_sha512 *state, unsigned char digest[32]);
+
+/* sha-384 digests */
+
+typedef struct fz_sha512_s fz_sha384;
+
+void fz_sha384_init(fz_sha384 *state);
+void fz_sha384_update(fz_sha384 *state, const unsigned char *input, unsigned int inlen);
+void fz_sha384_final(fz_sha384 *state, unsigned char digest[32]);
+
/* arc4 crypto */
typedef struct fz_arc4_s fz_arc4;
diff --git a/fitz/fitz.h b/fitz/fitz.h
index 90ae2717..34c7f237 100644
--- a/fitz/fitz.h
+++ b/fitz/fitz.h
@@ -121,6 +121,11 @@ int gettimeofday(struct timeval *tv, struct timezone *tz);
#endif
/*
+ Shut the compiler up about unused variables
+*/
+#define UNUSED(x) do { x = x; } while (0)
+
+/*
Some standard math functions, done as static inlines for speed.
People with compilers that do not adequately implement inlines may
like to reimplement these using macros.
diff --git a/fitz/image_png.c b/fitz/image_png.c
index f28203ee..7825eec2 100644
--- a/fitz/image_png.c
+++ b/fitz/image_png.c
@@ -5,7 +5,7 @@
struct info
{
fz_context *ctx;
- int width, height, depth, n;
+ unsigned int width, height, depth, n;
int interlace, indexed;
int size;
unsigned char *samples;
@@ -15,7 +15,7 @@ struct info
int xres, yres;
};
-static inline int getint(unsigned char *p)
+static inline unsigned int getuint(unsigned char *p)
{
return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
}
@@ -226,8 +226,8 @@ png_read_ihdr(struct info *info, unsigned char *p, int size)
if (size != 13)
fz_throw(info->ctx, "IHDR chunk is the wrong size");
- info->width = getint(p + 0);
- info->height = getint(p + 4);
+ info->width = getuint(p + 0);
+ info->height = getuint(p + 4);
info->depth = p[8];
color = p[9];
@@ -360,8 +360,8 @@ png_read_phys(struct info *info, unsigned char *p, int size)
fz_throw(info->ctx, "pHYs chunk is the wrong size");
if (p[8] == 1)
{
- info->xres = getint(p) * 254 / 10000;
- info->yres = getint(p + 4) * 254 / 10000;
+ info->xres = getuint(p) * 254 / 10000;
+ info->yres = getuint(p + 4) * 254 / 10000;
}
}
@@ -369,7 +369,7 @@ static void
png_read_image(fz_context *ctx, struct info *info, unsigned char *p, int total)
{
int passw[7], passh[7], passofs[8];
- int code, size;
+ unsigned int code, size;
z_stream stm;
memset(info, 0, sizeof (struct info));
@@ -388,7 +388,7 @@ png_read_image(fz_context *ctx, struct info *info, unsigned char *p, int total)
/* Read IHDR chunk (must come first) */
- size = getint(p);
+ size = getuint(p);
if (size + 12 > total)
fz_throw(info->ctx, "premature end of data in png image");
@@ -434,7 +434,7 @@ png_read_image(fz_context *ctx, struct info *info, unsigned char *p, int total)
/* Read remaining chunks until IEND */
while (total > 8)
{
- size = getint(p);
+ size = getuint(p);
if (size + 12 > total)
fz_throw(info->ctx, "premature end of data in png image");
diff --git a/fitz/memento.c b/fitz/memento.c
index 293c74e9..dcd417b8 100644
--- a/fitz/memento.c
+++ b/fitz/memento.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Artifex Software, Inc.
+/* Copyright (C) 2001-2012 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -6,16 +6,18 @@
This software is distributed under license and may not be copied, modified
or distributed except as expressly authorized under the terms of that
- license. Refer to licensing information at http://www.artifex.com/
+ license. Refer to licensing information at http://www.artifex.com
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
*/
+
/* Inspired by Fortify by Simon P Bullen. */
+
/* Set the following if you're only looking for leaks, not memory overwrites
* to speed the operation */
-#undef MEMENTO_LEAKONLY
+/* #define MEMENTO_LEAKONLY */
#ifndef MEMENTO_STACKTRACE_METHOD
#ifdef __GNUC__
@@ -28,9 +30,27 @@
#define MEMENTO_FREELIST_MAX_SINGLE_BLOCK (MEMENTO_FREELIST_MAX/4)
#define COMPILING_MEMENTO_C
+
+/* We have some GS specific tweaks; more for the GS build environment than
+ * anything else. */
+#undef MEMENTO_GS_HACKS
+
+#ifdef MEMENTO_GS_HACKS
+/* For GS we include malloc_.h. Anyone else would just include memento.h */
+#include "malloc_.h"
+#ifdef __MACH__
+#include <string.h>
+#else
+#ifndef memset
+void *memset(void *,int,size_t);
+#endif
+#endif
+int atexit(void (*)(void));
+#else
#include "memento.h"
#include <stdio.h>
#include <stdlib.h>
+#endif
#if defined(__linux__)
#define MEMENTO_HAS_FORK
@@ -48,8 +68,6 @@ void *MEMENTO_UNDERLYING_CALLOC(size_t,size_t);
* files, just in case they pull in unexpected others. */
int atoi(const char *);
char *getenv(const char *);
-//void *memset(void *,int,size_t);
-//int atexit(void (*)(void));
/* How far to search for pointers in each block when calculating nestings */
/* mupdf needs at least 34000ish (sizeof(fz_shade))/ */
@@ -61,6 +79,9 @@ char *getenv(const char *);
#ifdef MEMENTO
+#ifdef MEMENTO_GS_HACKS
+#include "valgrind.h"
+#else
#ifdef HAVE_VALGRIND
#include "valgrind/memcheck.h"
#else
@@ -68,6 +89,7 @@ char *getenv(const char *);
#define VALGRIND_MAKE_MEM_UNDEFINED(p,s) do { } while (0==1)
#define VALGRIND_MAKE_MEM_DEFINED(p,s) do { } while (0==1)
#endif
+#endif
enum {
Memento_PreSize = 16,
@@ -76,9 +98,30 @@ enum {
enum {
Memento_Flag_OldBlock = 1,
- Memento_Flag_HasParent = 2
+ Memento_Flag_HasParent = 2,
+ Memento_Flag_BreakOnFree = 4,
+ Memento_Flag_BreakOnRealloc = 8
};
+/* When we list leaked blocks at the end of execution, we search for pointers
+ * between blocks in order to be able to give a nice nested view.
+ * Unfortunately, if you have are running your own allocator (such as
+ * ghostscripts chunk allocator) you can often find that the header of the
+ * block always contains pointers to next or previous blocks. This tends to
+ * mean the nesting displayed is "uninteresting" at best :)
+ *
+ * As a hack to get around this, we have a define MEMENTO_SKIP_SEARCH that
+ * indicates how many bytes to skip over at the start of the chunk.
+ * This may cause us to miss true nestings, but such is life...
+ */
+#ifndef MEMENTO_SEARCH_SKIP
+#ifdef MEMENTO_GS_HACKS
+#define MEMENTO_SEARCH_SKIP (2*sizeof(void *))
+#else
+#define MEMENTO_SEARCH_SKIP 0
+#endif
+#endif
+
typedef struct Memento_BlkHeader Memento_BlkHeader;
struct Memento_BlkHeader
@@ -88,6 +131,7 @@ struct Memento_BlkHeader
int lastCheckedOK;
int flags;
Memento_BlkHeader *next;
+ Memento_BlkHeader *parent; /* Only used while printing out nested list */
const char *label;
@@ -321,6 +365,7 @@ static void Memento_removeBlock(Memento_Blocks *blks,
/* FAIL! Will have been reported to user earlier, so just exit. */
return;
}
+ VALGRIND_MAKE_MEM_DEFINED(blks->tail, sizeof(*blks->tail));
if (*blks->tail == head) {
/* Removing the tail of the list */
if (prev == NULL) {
@@ -428,12 +473,14 @@ static void showBlock(Memento_BlkHeader *b, int space)
static void blockDisplay(Memento_BlkHeader *b, int n)
{
- int i = 0;
n++;
- while(i < n)
+ while(n > 0)
{
- fprintf(stderr, "%s", &" "[32-((n-i)&31)]);
- i += ((n-i)&31);
+ int i = n;
+ if (i > 32)
+ i = 32;
+ n -= i;
+ fprintf(stderr, "%s", &" "[32-i]);
}
showBlock(b, '\t');
fprintf(stderr, "\n");
@@ -464,12 +511,13 @@ static int ptrcmp(const void *a_, const void *b_)
return (int)(*a-*b);
}
+static
int Memento_listBlocksNested(void)
{
int count, size, i;
Memento_BlkHeader *b;
void **blocks, *minptr, *maxptr;
- int mask;
+ long mask;
/* Count the blocks */
count = 0;
@@ -487,10 +535,10 @@ int Memento_listBlocksNested(void)
/* Populate our block list */
b = globals.used.head;
minptr = maxptr = MEMBLK_TOBLK(b);
- mask = (int)minptr;
+ mask = (long)minptr;
for (i = 0; b; b = b->next, i++) {
void *p = MEMBLK_TOBLK(b);
- mask &= (int)p;
+ mask &= (long)p;
if (p < minptr)
minptr = p;
if (p > maxptr)
@@ -499,6 +547,7 @@ int Memento_listBlocksNested(void)
b->flags &= ~Memento_Flag_HasParent;
b->child = NULL;
b->sibling = NULL;
+ b->parent = NULL;
}
qsort(blocks, count, sizeof(void *), ptrcmp);
@@ -506,7 +555,7 @@ int Memento_listBlocksNested(void)
for (b = globals.used.head; b; b = b->next) {
char *p = MEMBLK_TOBLK(b);
int end = (b->rawsize < MEMENTO_PTRSEARCH ? b->rawsize : MEMENTO_PTRSEARCH);
- for (i = 0; i < end; i += sizeof(void *)) {
+ for (i = MEMENTO_SEARCH_SKIP; i < end; i += sizeof(void *)) {
void *q = *(void **)(&p[i]);
void **r;
@@ -519,14 +568,26 @@ int Memento_listBlocksNested(void)
if (r) {
/* Found child */
Memento_BlkHeader *child = MEMBLK_FROMBLK(*r);
+ Memento_BlkHeader *parent;
/* We're assuming tree structure, not graph - ignore second
* and subsequent pointers. */
+ if (child->parent != NULL)
+ continue;
if (child->flags & Memento_Flag_HasParent)
continue;
+ /* We're also assuming acyclicness here. If this is one of
+ * our parents, ignore it. */
+ parent = b->parent;
+ while (parent != NULL && parent != child)
+ parent = parent->parent;
+ if (parent == child)
+ continue;
+
child->sibling = b->child;
b->child = child;
+ child->parent = b;
child->flags |= Memento_Flag_HasParent;
}
}
@@ -974,6 +1035,9 @@ void Memento_free(void *blk)
if (checkBlock(memblk, "free"))
return;
+ if (memblk->flags & Memento_Flag_BreakOnFree)
+ Memento_breakpoint();
+
VALGRIND_MAKE_MEM_DEFINED(memblk, sizeof(*memblk));
globals.alloc -= memblk->rawsize;
globals.numFrees++;
@@ -998,6 +1062,7 @@ void *Memento_realloc(void *blk, size_t newsize)
{
Memento_BlkHeader *memblk, *newmemblk;
size_t newsizemem;
+ int flags;
if (blk == NULL)
return Memento_malloc(newsize);
@@ -1013,11 +1078,15 @@ void *Memento_realloc(void *blk, size_t newsize)
if (checkBlock(memblk, "realloc"))
return NULL;
+ if (memblk->flags & Memento_Flag_BreakOnRealloc)
+ Memento_breakpoint();
+
if (globals.maxMemory != 0 && globals.alloc - memblk->rawsize + newsize > globals.maxMemory)
return NULL;
newsizemem = MEMBLK_SIZE(newsize);
Memento_removeBlock(&globals.used, memblk);
+ flags = memblk->flags;
newmemblk = MEMENTO_UNDERLYING_REALLOC(memblk, newsizemem);
if (newmemblk == NULL)
{
@@ -1030,6 +1099,7 @@ void *Memento_realloc(void *blk, size_t newsize)
globals.alloc += newsize;
if (globals.peakAlloc < globals.alloc)
globals.peakAlloc = globals.alloc;
+ newmemblk->flags = flags;
if (newmemblk->rawsize < newsize) {
char *newbytes = ((char *)MEMBLK_TOBLK(newmemblk))+newmemblk->rawsize;
#ifndef MEMENTO_LEAKONLY
@@ -1241,6 +1311,72 @@ int Memento_find(void *a)
return 0;
}
+void Memento_breakOnFree(void *a)
+{
+ findBlkData data;
+
+ data.addr = a;
+ data.blk = NULL;
+ data.flags = 0;
+ Memento_appBlocks(&globals.used, Memento_containsAddr, &data);
+ if (data.blk != NULL) {
+ fprintf(stderr, "Will stop when address 0x%p (in %sallocated block ",
+ data.addr,
+ (data.flags == 1 ? "" : (data.flags == 2 ?
+ "preguard of " : "postguard of ")));
+ showBlock(data.blk, ' ');
+ fprintf(stderr, ") is freed\n");
+ data.blk->flags |= Memento_Flag_BreakOnFree;
+ return;
+ }
+ data.blk = NULL;
+ data.flags = 0;
+ Memento_appBlocks(&globals.free, Memento_containsAddr, &data);
+ if (data.blk != NULL) {
+ fprintf(stderr, "Can't stop on free; address 0x%p is in %sfreed block ",
+ data.addr,
+ (data.flags == 1 ? "" : (data.flags == 2 ?
+ "preguard of " : "postguard of ")));
+ showBlock(data.blk, ' ');
+ fprintf(stderr, "\n");
+ return;
+ }
+ fprintf(stderr, "Can't stop on free; address 0x%p is not in a known block.\n", a);
+}
+
+void Memento_breakOnRealloc(void *a)
+{
+ findBlkData data;
+
+ data.addr = a;
+ data.blk = NULL;
+ data.flags = 0;
+ Memento_appBlocks(&globals.used, Memento_containsAddr, &data);
+ if (data.blk != NULL) {
+ fprintf(stderr, "Will stop when address 0x%p (in %sallocated block ",
+ data.addr,
+ (data.flags == 1 ? "" : (data.flags == 2 ?
+ "preguard of " : "postguard of ")));
+ showBlock(data.blk, ' ');
+ fprintf(stderr, ") is freed (or realloced)\n");
+ data.blk->flags |= Memento_Flag_BreakOnFree | Memento_Flag_BreakOnRealloc;
+ return;
+ }
+ data.blk = NULL;
+ data.flags = 0;
+ Memento_appBlocks(&globals.free, Memento_containsAddr, &data);
+ if (data.blk != NULL) {
+ fprintf(stderr, "Can't stop on free/realloc; address 0x%p is in %sfreed block ",
+ data.addr,
+ (data.flags == 1 ? "" : (data.flags == 2 ?
+ "preguard of " : "postguard of ")));
+ showBlock(data.blk, ' ');
+ fprintf(stderr, "\n");
+ return;
+ }
+ fprintf(stderr, "Can't stop on free/realloc; address 0x%p is not in a known block.\n", a);
+}
+
int Memento_failAt(int i)
{
globals.failAt = i;
@@ -1308,6 +1444,14 @@ int (Memento_failAt)(int i)
return 0;
}
+void (Memento_breakOnFree)(void *a)
+{
+}
+
+void (Memento_breakOnRealloc)(void *a)
+{
+}
+
#undef Memento_malloc
#undef Memento_free
#undef Memento_realloc
diff --git a/fitz/memento.h b/fitz/memento.h
index e4b7778f..4831349b 100644
--- a/fitz/memento.h
+++ b/fitz/memento.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011 Artifex Software, Inc.
+/* Copyright (C) 2001-2012 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -6,11 +6,12 @@
This software is distributed under license and may not be copied, modified
or distributed except as expressly authorized under the terms of that
- license. Refer to licensing information at http://www.artifex.com/
+ license. Refer to licensing information at http://www.artifex.com
or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134,
San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information.
*/
+
/* Memento: A library to aid debugging of memory leaks/heap corruption.
*
* Usage:
@@ -169,6 +170,8 @@ int Memento_check(void);
int Memento_setParanoia(int);
int Memento_paranoidAt(int);
int Memento_breakAt(int);
+void Memento_breakOnFree(void *a);
+void Memento_breakOnRealloc(void *a);
int Memento_getBlockNum(void *);
int Memento_find(void *a);
void Memento_breakpoint(void);
@@ -201,22 +204,24 @@ void *Memento_calloc(size_t, size_t);
#define Memento_realloc MEMENTO_UNDERLYING_REALLOC
#define Memento_calloc MEMENTO_UNDERLYING_CALLOC
-#define Memento_checkBlock(A) 0
-#define Memento_checkAllMemory() 0
-#define Memento_check() 0
-#define Memento_setParanoia(A) 0
-#define Memento_paranoidAt(A) 0
-#define Memento_breakAt(A) 0
-#define Memento_getBlockNum(A) 0
-#define Memento_find(A) 0
-#define Memento_breakpoint() do {} while (0)
-#define Memento_failAt(A) 0
-#define Memento_failThisEvent() 0
-#define Memento_listBlocks() do {} while (0)
-#define Memento_listNewBlocks() do {} while (0)
-#define Memento_setMax(A) 0
-#define Memento_stats() do {} while (0)
-#define Memento_label(A,B) (A)
+#define Memento_checkBlock(A) 0
+#define Memento_checkAllMemory() 0
+#define Memento_check() 0
+#define Memento_setParanoia(A) 0
+#define Memento_paranoidAt(A) 0
+#define Memento_breakAt(A) 0
+#define Memento_breakOnFree(A) 0
+#define Memento_breakOnRealloc(A) 0
+#define Memento_getBlockNum(A) 0
+#define Memento_find(A) 0
+#define Memento_breakpoint() do {} while (0)
+#define Memento_failAt(A) 0
+#define Memento_failThisEvent() 0
+#define Memento_listBlocks() do {} while (0)
+#define Memento_listNewBlocks() do {} while (0)
+#define Memento_setMax(A) 0
+#define Memento_stats() do {} while (0)
+#define Memento_label(A,B) (A)
#endif /* MEMENTO */
diff --git a/fitz/res_font.c b/fitz/res_font.c
index 50420d97..77cae676 100644
--- a/fitz/res_font.c
+++ b/fitz/res_font.c
@@ -568,7 +568,7 @@ fz_render_ft_stroked_glyph(fz_context *ctx, fz_font *font, int gid, fz_matrix tr
state->linejoin == FZ_LINEJOIN_BEVEL ? FT_STROKER_LINEJOIN_BEVEL :
FT_STROKER_LINEJOIN_MITER;
#endif
- FT_Stroker_Set(stroker, linewidth, state->start_cap, line_join, state->miterlimit * 65536);
+ FT_Stroker_Set(stroker, linewidth, (FT_Stroker_LineCap)state->start_cap, line_join, state->miterlimit * 65536);
fterr = FT_Get_Glyph(face->glyph, &glyph);
if (fterr)
diff --git a/ios/Info.plist b/ios/Info.plist
index 1e29c114..2b181b3d 100644
--- a/ios/Info.plist
+++ b/ios/Info.plist
@@ -19,11 +19,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
- <string>1.0</string>
+ <string>1.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>1.0</string>
+ <string>1.1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIFileSharingEnabled</key>
diff --git a/ios/MuPDF.xcodeproj/project.pbxproj b/ios/MuPDF.xcodeproj/project.pbxproj
index 1c047a36..f7b1f956 100644
--- a/ios/MuPDF.xcodeproj/project.pbxproj
+++ b/ios/MuPDF.xcodeproj/project.pbxproj
@@ -14,6 +14,8 @@
968F2EA014539C880085264E /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 968F2E9F14539C880085264E /* CoreGraphics.framework */; };
968F2EB014539CDA0085264E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 968F2E9014539BEB0085264E /* main.m */; };
96A4739B147C1C3A003D757D /* libLibraries.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 968461E214642DB00012AE09 /* libLibraries.a */; };
+ 96B6AF8315D16A7E00EAAF7B /* x_alt_blue.png in Resources */ = {isa = PBXBuildFile; fileRef = 96B6AF8115D16A7E00EAAF7B /* x_alt_blue.png */; };
+ 96B6AF8415D16A7E00EAAF7B /* x_alt_blue@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 96B6AF8215D16A7E00EAAF7B /* x_alt_blue@2x.png */; };
96BD2B38145AC485001CEBC3 /* Icon-72.png in Resources */ = {isa = PBXBuildFile; fileRef = 96BD2B35145AC485001CEBC3 /* Icon-72.png */; };
96BD2B39145AC485001CEBC3 /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 96BD2B36145AC485001CEBC3 /* Icon.png */; };
96F2341514603FBA004A8A22 /* Icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 96F2341414603FBA004A8A22 /* Icon@2x.png */; };
@@ -41,6 +43,8 @@
968F2E9B14539C880085264E /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
968F2E9D14539C880085264E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; };
968F2E9F14539C880085264E /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; };
+ 96B6AF8115D16A7E00EAAF7B /* x_alt_blue.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = x_alt_blue.png; sourceTree = "<group>"; };
+ 96B6AF8215D16A7E00EAAF7B /* x_alt_blue@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "x_alt_blue@2x.png"; sourceTree = "<group>"; };
96BD2B35145AC485001CEBC3 /* Icon-72.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-72.png"; sourceTree = "<group>"; };
96BD2B36145AC485001CEBC3 /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Icon.png; sourceTree = "<group>"; };
96F2341414603FBA004A8A22 /* Icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon@2x.png"; sourceTree = "<group>"; };
@@ -68,6 +72,8 @@
96BD2B36145AC485001CEBC3 /* Icon.png */,
96F2341414603FBA004A8A22 /* Icon@2x.png */,
96BD2B35145AC485001CEBC3 /* Icon-72.png */,
+ 96B6AF8115D16A7E00EAAF7B /* x_alt_blue.png */,
+ 96B6AF8215D16A7E00EAAF7B /* x_alt_blue@2x.png */,
968F2E8F14539BEB0085264E /* Info.plist */,
968F2E8E14539BEB0085264E /* build_libs.sh */,
9644E99E146ACEC000E5B70A /* document.c */,
@@ -176,6 +182,8 @@
96BD2B39145AC485001CEBC3 /* Icon.png in Resources */,
96F2341514603FBA004A8A22 /* Icon@2x.png in Resources */,
9668C8D91476A30200D7BA52 /* About.xps in Resources */,
+ 96B6AF8315D16A7E00EAAF7B /* x_alt_blue.png in Resources */,
+ 96B6AF8415D16A7E00EAAF7B /* x_alt_blue@2x.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/ios/main.m b/ios/main.m
index f24e2bdd..0f80505d 100644
--- a/ios/main.m
+++ b/ios/main.m
@@ -20,7 +20,7 @@ static dispatch_queue_t queue;
static float screenScale = 1;
static fz_context *ctx = NULL;
-@interface MuLibraryController : UITableViewController
+@interface MuLibraryController : UITableViewController <UIActionSheetDelegate>
{
NSArray *files;
NSTimer *timer;
@@ -189,7 +189,7 @@ static CGSize fitPageToScreen(CGSize page, CGSize screen)
{
float hscale = screen.width / page.width;
float vscale = screen.height / page.height;
- float scale = MIN(hscale, vscale);
+ float scale = fz_min(hscale, vscale);
hscale = floorf(page.width * scale) / page.width;
vscale = floorf(page.height * scale) / page.height;
return CGSizeMake(hscale, vscale);
@@ -335,6 +335,42 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
return [files count] + 1;
}
+- (void) actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
+{
+ if (buttonIndex == [actionSheet destructiveButtonIndex])
+ {
+ char filename[PATH_MAX];
+ int row = [actionSheet tag];
+
+ dispatch_sync(queue, ^{});
+
+ strcpy(filename, [NSHomeDirectory() UTF8String]);
+ strcat(filename, "/Documents/");
+ strcat(filename, [[files objectAtIndex: row - 1] UTF8String]);
+
+ printf("delete document '%s'\n", filename);
+
+ unlink(filename);
+
+ [self reload];
+ }
+}
+
+- (void) onTapDelete: (UIControl*)sender
+{
+ int row = [sender tag];
+ NSString *title = [NSString stringWithFormat: @"Delete %@?", [files objectAtIndex: row - 1]];
+ UIActionSheet *sheet = [[UIActionSheet alloc]
+ initWithTitle: title
+ delegate: self
+ cancelButtonTitle: @"Cancel"
+ destructiveButtonTitle: @"Delete"
+ otherButtonTitles: nil];
+ [sheet setTag: row];
+ [sheet showInView: [self tableView]];
+ [sheet release];
+}
+
- (UITableViewCell*) tableView: (UITableView*)tableView cellForRowAtIndexPath: (NSIndexPath*)indexPath
{
static NSString *cellid = @"MuCellIdent";
@@ -345,11 +381,25 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
if (row == 0) {
[[cell textLabel] setText: @"About MuPDF"];
[[cell textLabel] setFont: [UIFont systemFontOfSize: 20]];
-// [[cell textLabel] setFont: [UIFont italicSystemFontOfSize: 20]];
} else {
[[cell textLabel] setText: [files objectAtIndex: row - 1]];
[[cell textLabel] setFont: [UIFont systemFontOfSize: 20]];
}
+
+ if (row > 0)
+ {
+ UIButton *deleteButton = [UIButton buttonWithType:UIButtonTypeCustom];
+ [deleteButton setImage: [UIImage imageNamed: @"x_alt_blue.png"] forState: UIControlStateNormal];
+ [deleteButton setFrame: CGRectMake(0, 0, 35, 35)];
+ [deleteButton addTarget: self action: @selector(onTapDelete:) forControlEvents: UIControlEventTouchUpInside];
+ [deleteButton setTag: row];
+ [cell setAccessoryView: deleteButton];
+ }
+ else
+ {
+ [cell setAccessoryView: nil];
+ }
+
return cell;
}
@@ -485,11 +535,13 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
static NSString *cellid = @"MuCellIdent";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: cellid];
if (!cell)
+ {
cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleValue1 reuseIdentifier: cellid] autorelease];
+ [[cell textLabel] setFont: [UIFont systemFontOfSize: 16]];
+ [[cell detailTextLabel] setFont: [UIFont systemFontOfSize: 16]];
+ }
NSString *title = [titles objectAtIndex: [indexPath row]];
NSString *page = [pages objectAtIndex: [indexPath row]];
- [[cell textLabel] setFont: [UIFont systemFontOfSize: 16]];
- [[cell detailTextLabel] setFont: [UIFont systemFontOfSize: 16]];
[[cell textLabel] setText: title];
[[cell detailTextLabel] setText: [NSString stringWithFormat: @"%d", [page intValue]+1]];
return cell;
@@ -1001,16 +1053,23 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
- (void) viewWillAppear: (BOOL)animated
{
- CGSize size = [canvas frame].size;
- width = size.width;
- height = size.height;
-
[self setTitle: [key lastPathComponent]];
[slider setValue: current];
[indicator setText: [NSString stringWithFormat: @" %d of %d ", current+1, count_pages(doc)]];
+ [[self navigationController] setToolbarHidden: NO animated: animated];
+}
+
+- (void) viewWillLayoutSubviews
+{
+ CGSize size = [canvas frame].size;
+ int max_width = fz_max(width, size.width);
+
+ width = size.width;
+ height = size.height;
+
[canvas setContentInset: UIEdgeInsetsZero];
[canvas setContentSize: CGSizeMake(count_pages(doc) * width, height)];
[canvas setContentOffset: CGPointMake(current * width, 0)];
@@ -1018,7 +1077,24 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
[sliderWrapper setWidth: SLIDER_W];
[searchBar setFrame: CGRectMake(0,0,SEARCH_W,32)];
- [[self navigationController] setToolbarHidden: NO animated: animated];
+ [[[self navigationController] toolbar] setNeedsLayout]; // force layout!
+
+ // use max_width so we don't clamp the content offset too early during animation
+ [canvas setContentSize: CGSizeMake(count_pages(doc) * max_width, height)];
+ [canvas setContentOffset: CGPointMake(current * width, 0)];
+
+ for (MuPageView *view in [canvas subviews]) {
+ if ([view number] == current) {
+ [view setFrame: CGRectMake([view number] * width, 0, width-GAP, height)];
+ [view willRotate];
+ }
+ }
+ for (MuPageView *view in [canvas subviews]) {
+ if ([view number] != current) {
+ [view setFrame: CGRectMake([view number] * width, 0, width-GAP, height)];
+ [view willRotate];
+ }
+ }
}
- (void) viewDidAppear: (BOOL)animated
@@ -1349,37 +1425,6 @@ static UIImage *renderTile(struct document *doc, int number, CGSize screenSize,
return YES;
}
-- (void) willAnimateRotationToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
-{
- CGSize size = [canvas frame].size;
- int max_width = MAX(width, size.width);
-
- width = size.width;
- height = size.height;
-
- [sliderWrapper setWidth: SLIDER_W];
- [searchBar setFrame: CGRectMake(0,0,SEARCH_W,32)];
-
- [[[self navigationController] toolbar] setNeedsLayout]; // force layout!
-
- // use max_width so we don't clamp the content offset too early during animation
- [canvas setContentSize: CGSizeMake(count_pages(doc) * max_width, height)];
- [canvas setContentOffset: CGPointMake(current * width, 0)];
-
- for (MuPageView *view in [canvas subviews]) {
- if ([view number] == current) {
- [view setFrame: CGRectMake([view number] * width, 0, width-GAP, height)];
- [view willRotate];
- }
- }
- for (MuPageView *view in [canvas subviews]) {
- if ([view number] != current) {
- [view setFrame: CGRectMake([view number] * width, 0, width-GAP, height)];
- [view willRotate];
- }
- }
-}
-
- (void) didRotateFromInterfaceOrientation: (UIInterfaceOrientation)o
{
[canvas setContentSize: CGSizeMake(count_pages(doc) * width, height)];
diff --git a/ios/x_alt_blue.png b/ios/x_alt_blue.png
new file mode 100644
index 00000000..0ca9a6cc
--- /dev/null
+++ b/ios/x_alt_blue.png
Binary files differ
diff --git a/ios/x_alt_blue@2x.png b/ios/x_alt_blue@2x.png
new file mode 100644
index 00000000..1cb67549
--- /dev/null
+++ b/ios/x_alt_blue@2x.png
Binary files differ
diff --git a/pdf/mupdf.h b/pdf/mupdf.h
index f2d235b9..16b0f58b 100644
--- a/pdf/mupdf.h
+++ b/pdf/mupdf.h
@@ -17,7 +17,7 @@ pdf_obj *pdf_new_null(fz_context *ctx);
pdf_obj *pdf_new_bool(fz_context *ctx, int b);
pdf_obj *pdf_new_int(fz_context *ctx, int i);
pdf_obj *pdf_new_real(fz_context *ctx, float f);
-pdf_obj *fz_new_name(fz_context *ctx, char *str);
+pdf_obj *pdf_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);
diff --git a/pdf/pdf_annot.c b/pdf/pdf_annot.c
index 5a463336..18a0c947 100644
--- a/pdf/pdf_annot.c
+++ b/pdf/pdf_annot.c
@@ -198,6 +198,8 @@ pdf_parse_action(pdf_document *xref, pdf_obj *action)
pdf_obj *obj, *dest;
fz_context *ctx = xref->ctx;
+ UNUSED(ctx);
+
ld.kind = FZ_LINK_NONE;
if (!action)
diff --git a/pdf/pdf_crypt.c b/pdf/pdf_crypt.c
index 5329e845..ec6f792b 100644
--- a/pdf/pdf_crypt.c
+++ b/pdf/pdf_crypt.c
@@ -103,8 +103,8 @@ pdf_new_crypt(fz_context *ctx, pdf_obj *dict, pdf_obj *id)
obj = pdf_dict_gets(dict, "O");
if (pdf_is_string(obj) && pdf_to_str_len(obj) == 32)
memcpy(crypt->o, pdf_to_str_buf(obj), 32);
- /* /O and /U are supposed to be 48 bytes long for revision 5, they're often longer, though */
- else if (crypt->r == 5 && pdf_is_string(obj) && pdf_to_str_len(obj) >= 48)
+ /* /O and /U are supposed to be 48 bytes long for revision 5 and 6, they're often longer, though */
+ else if (crypt->r >= 5 && pdf_is_string(obj) && pdf_to_str_len(obj) >= 48)
memcpy(crypt->o, pdf_to_str_buf(obj), 48);
else
{
@@ -115,8 +115,8 @@ pdf_new_crypt(fz_context *ctx, pdf_obj *dict, pdf_obj *id)
obj = pdf_dict_gets(dict, "U");
if (pdf_is_string(obj) && pdf_to_str_len(obj) == 32)
memcpy(crypt->u, pdf_to_str_buf(obj), 32);
- /* /O and /U are supposed to be 48 bytes long for revision 5, they're often longer, though */
- else if (crypt->r == 5 && pdf_is_string(obj) && pdf_to_str_len(obj) >= 48)
+ /* /O and /U are supposed to be 48 bytes long for revision 5 and 6, they're often longer, though */
+ else if (crypt->r >= 5 && pdf_is_string(obj) && pdf_to_str_len(obj) >= 48)
memcpy(crypt->u, pdf_to_str_buf(obj), 48);
else if (pdf_is_string(obj) && pdf_to_str_len(obj) < 32)
{
@@ -138,7 +138,7 @@ pdf_new_crypt(fz_context *ctx, pdf_obj *dict, pdf_obj *id)
crypt->p = 0xfffffffc;
}
- if (crypt->r == 5)
+ if (crypt->r == 5 || crypt->r == 6)
{
obj = pdf_dict_gets(dict, "OE");
if (!pdf_is_string(obj) || pdf_to_str_len(obj) != 32)
@@ -315,10 +315,9 @@ pdf_parse_crypt_filter(fz_context *ctx, pdf_crypt_filter *cf, pdf_crypt *crypt,
fz_throw(ctx, "invalid key length: %d", cf->length);
if ((crypt->r == 1 || crypt->r == 2 || crypt->r == 4) &&
- (cf->length < 0 || cf->length > 256))
+ (cf->length < 0 || cf->length > 128))
fz_throw(ctx, "invalid key length: %d", cf->length);
- if (crypt->r == 5 &&
- (cf->length != 128 && cf->length != 192 && cf->length == 256))
+ if ((crypt->r == 5 || crypt->r == 6) && cf->length != 256)
fz_throw(ctx, "invalid key length: %d", cf->length);
}
@@ -445,6 +444,101 @@ pdf_compute_encryption_key_r5(pdf_crypt *crypt, unsigned char *password, int pwl
}
/*
+ * Compute an encryption key (PDF 1.7 ExtensionLevel 8 algorithm)
+ *
+ * Adobe has not yet released the details, so the algorithm reference is:
+ * http://esec-lab.sogeti.com/post/The-undocumented-password-validation-algorithm-of-Adobe-Reader-X
+ */
+
+static void
+pdf_compute_hardened_hash_r6(unsigned char *password, int pwlen, unsigned char salt[16], unsigned char *ownerkey, unsigned char hash[32])
+{
+ unsigned char data[(128 + 64 + 48) * 64];
+ unsigned char block[64];
+ int block_size = 32;
+ int data_len = 0;
+ int i, j, sum;
+
+ fz_sha256 sha256;
+ fz_sha384 sha384;
+ fz_sha512 sha512;
+ fz_aes aes;
+
+ /* Step 1: calculate initial data block */
+ fz_sha256_init(&sha256);
+ fz_sha256_update(&sha256, password, pwlen);
+ fz_sha256_update(&sha256, salt, 8);
+ if (ownerkey)
+ fz_sha256_update(&sha256, ownerkey, 48);
+ fz_sha256_final(&sha256, block);
+
+ for (i = 0; i < 64 || i < data[data_len * 64 - 1] + 32; i++)
+ {
+ /* Step 2: repeat password and data block 64 times */
+ memcpy(data, password, pwlen);
+ memcpy(data + pwlen, block, block_size);
+ memcpy(data + pwlen + block_size, ownerkey, ownerkey ? 48 : 0);
+ data_len = pwlen + block_size + (ownerkey ? 48 : 0);
+ for (j = 1; j < 64; j++)
+ memcpy(data + j * data_len, data, data_len);
+
+ /* Step 3: encrypt data using data block as key and iv */
+ aes_setkey_enc(&aes, block, 128);
+ aes_crypt_cbc(&aes, AES_ENCRYPT, data_len * 64, block + 16, data, data);
+
+ /* Step 4: determine SHA-2 hash size for this round */
+ for (j = 0, sum = 0; j < 16; j++)
+ sum += data[j];
+
+ /* Step 5: calculate data block for next round */
+ block_size = 32 + (sum % 3) * 16;
+ switch (block_size)
+ {
+ case 32:
+ fz_sha256_init(&sha256);
+ fz_sha256_update(&sha256, data, data_len * 64);
+ fz_sha256_final(&sha256, block);
+ break;
+ case 48:
+ fz_sha384_init(&sha384);
+ fz_sha384_update(&sha384, data, data_len * 64);
+ fz_sha384_final(&sha384, block);
+ break;
+ case 64:
+ fz_sha512_init(&sha512);
+ fz_sha512_update(&sha512, data, data_len * 64);
+ fz_sha512_final(&sha512, block);
+ break;
+ }
+ }
+
+ memset(data, 0, sizeof(data));
+ memcpy(hash, block, 32);
+}
+
+static void
+pdf_compute_encryption_key_r6(pdf_crypt *crypt, unsigned char *password, int pwlen, int ownerkey, unsigned char *validationkey)
+{
+ unsigned char hash[32];
+ unsigned char iv[16];
+ fz_aes aes;
+
+ if (pwlen > 127)
+ pwlen = 127;
+
+ pdf_compute_hardened_hash_r6(password, pwlen,
+ (ownerkey ? crypt->o : crypt->u) + 32,
+ ownerkey ? crypt->u : NULL, validationkey);
+ pdf_compute_hardened_hash_r6(password, pwlen,
+ crypt->u + 40, NULL, hash);
+
+ memset(iv, 0, sizeof(iv));
+ aes_setkey_dec(&aes, hash, 256);
+ aes_crypt_cbc(&aes, AES_DECRYPT, 32, iv,
+ ownerkey ? crypt->oe : crypt->ue, crypt->key);
+}
+
+/*
* Computing the user password (PDF 1.7 algorithm 3.4 and 3.5)
* Also save the generated key for decrypting objects and streams in crypt->key.
*/
@@ -496,6 +590,11 @@ pdf_compute_user_password(pdf_crypt *crypt, unsigned char *password, int pwlen,
{
pdf_compute_encryption_key_r5(crypt, password, pwlen, 0, output);
}
+
+ if (crypt->r == 6)
+ {
+ pdf_compute_encryption_key_r6(crypt, password, pwlen, 0, output);
+ }
}
/*
@@ -510,7 +609,7 @@ pdf_authenticate_user_password(pdf_crypt *crypt, unsigned char *password, int pw
{
unsigned char output[32];
pdf_compute_user_password(crypt, password, pwlen, output);
- if (crypt->r == 2 || crypt->r == 5)
+ if (crypt->r == 2 || crypt->r == 5 || crypt->r == 6)
return memcmp(output, crypt->u, 32) == 0;
if (crypt->r == 3 || crypt->r == 4)
return memcmp(output, crypt->u, 16) == 0;
@@ -538,9 +637,13 @@ pdf_authenticate_owner_password(pdf_crypt *crypt, unsigned char *ownerpass, int
if (crypt->r == 5)
{
/* PDF 1.7 ExtensionLevel 3 algorithm 3.12 */
-
pdf_compute_encryption_key_r5(crypt, ownerpass, pwlen, 1, key);
-
+ return !memcmp(key, crypt->o, 32);
+ }
+ else if (crypt->r == 6)
+ {
+ /* PDF 1.7 ExtensionLevel 8 algorithm */
+ pdf_compute_encryption_key_r6(crypt, ownerpass, pwlen, 1, key);
return !memcmp(key, crypt->o, 32);
}
diff --git a/pdf/pdf_form.c b/pdf/pdf_form.c
index cb92956f..1a902df3 100644
--- a/pdf/pdf_form.c
+++ b/pdf/pdf_form.c
@@ -1452,7 +1452,7 @@ static void reset_field(pdf_document *doc, pdf_obj *obj)
fz_var(name);
fz_try(ctx)
{
- name = fz_new_name(ctx, "Off");
+ name = pdf_new_name(ctx, "Off");
pdf_dict_puts(obj, "AS", name);
}
fz_always(ctx)
@@ -1612,7 +1612,7 @@ static void check_off(fz_context *ctx, pdf_obj *obj)
fz_var(off);
fz_try(ctx);
{
- off = fz_new_name(ctx, "Off");
+ off = pdf_new_name(ctx, "Off");
pdf_dict_puts(obj, "AS", off);
}
fz_always(ctx)
@@ -1636,9 +1636,9 @@ static void set_check(fz_context *ctx, pdf_obj *chk, char *name)
/* If name is a possible value of this check
* box then use it, otherwise use "Off" */
if (pdf_dict_gets(n, name))
- val = fz_new_name(ctx, name);
+ val = pdf_new_name(ctx, name);
else
- val = fz_new_name(ctx, "Off");
+ val = pdf_new_name(ctx, "Off");
pdf_dict_puts(chk, "AS", val);
}
@@ -1947,15 +1947,15 @@ void pdf_field_setBorderStyle(pdf_document *doc, pdf_obj *field, char *text)
pdf_obj *val = NULL;
if (!strcmp(text, "Solid"))
- val = fz_new_name(ctx, "S");
+ val = pdf_new_name(ctx, "S");
else if (!strcmp(text, "Dashed"))
- val = fz_new_name(ctx, "D");
+ val = pdf_new_name(ctx, "D");
else if (!strcmp(text, "Beveled"))
- val = fz_new_name(ctx, "B");
+ val = pdf_new_name(ctx, "B");
else if (!strcmp(text, "Inset"))
- val = fz_new_name(ctx, "I");
+ val = pdf_new_name(ctx, "I");
else if (!strcmp(text, "Underline"))
- val = fz_new_name(ctx, "U");
+ val = pdf_new_name(ctx, "U");
else
return;
diff --git a/pdf/pdf_interpret.c b/pdf/pdf_interpret.c
index 704f6e78..f596b0ed 100644
--- a/pdf/pdf_interpret.c
+++ b/pdf/pdf_interpret.c
@@ -1538,7 +1538,7 @@ pdf_run_extgstate(pdf_csi *csi, pdf_obj *rdb, pdf_obj *extgstate)
if (pdf_is_dict(val))
{
pdf_xobject *xobj;
- pdf_obj *group, *luminosity, *bc;
+ pdf_obj *group, *luminosity, *bc, *tr;
if (gstate->softmask)
{
@@ -1572,6 +1572,19 @@ pdf_run_extgstate(pdf_csi *csi, pdf_obj *rdb, pdf_obj *extgstate)
gstate->luminosity = 1;
else
gstate->luminosity = 0;
+
+ tr = pdf_dict_gets(val, "TR2");
+ if (tr)
+ {
+ if (strcmp(pdf_to_name(tr), "Identity") && strcmp(pdf_to_name(tr), "Default"))
+ fz_warn(ctx, "ignoring transfer function");
+ }
+ else
+ {
+ tr = pdf_dict_gets(val, "TR");
+ if (strcmp(pdf_to_name(tr), "Identity"))
+ fz_warn(ctx, "ignoring transfer function");
+ }
}
else if (pdf_is_name(val) && !strcmp(pdf_to_name(val), "None"))
{
diff --git a/pdf/pdf_nametree.c b/pdf/pdf_nametree.c
index 25fced52..ab3244d3 100644
--- a/pdf/pdf_nametree.c
+++ b/pdf/pdf_nametree.c
@@ -118,6 +118,8 @@ pdf_load_name_tree_imp(pdf_obj *dict, pdf_document *xref, pdf_obj *node)
pdf_obj *names = pdf_dict_gets(node, "Names");
int i;
+ UNUSED(ctx);
+
if (kids && !pdf_dict_mark(node))
{
int len = pdf_array_len(kids);
diff --git a/pdf/pdf_object.c b/pdf/pdf_object.c
index fb53d9b8..3a1e7655 100644
--- a/pdf/pdf_object.c
+++ b/pdf/pdf_object.c
@@ -117,7 +117,7 @@ pdf_new_string(fz_context *ctx, char *str, int len)
}
pdf_obj *
-fz_new_name(fz_context *ctx, char *str)
+pdf_new_name(fz_context *ctx, char *str)
{
pdf_obj *obj;
obj = Memento_label(fz_malloc(ctx, offsetof(pdf_obj, u.n) + strlen(str) + 1), "pdf_obj(name)");
@@ -588,12 +588,12 @@ pdf_obj *pdf_new_rect(fz_context *ctx, fz_rect *rect)
pdf_drop_obj(item);
item = NULL;
- item = pdf_new_real(ctx, rect->x1 - rect->x0);
+ item = pdf_new_real(ctx, rect->x1);
pdf_array_push(arr, item);
pdf_drop_obj(item);
item = NULL;
- item = pdf_new_real(ctx, rect->y1 - rect->y0);
+ item = pdf_new_real(ctx, rect->y1);
pdf_array_push(arr, item);
pdf_drop_obj(item);
item = NULL;
@@ -945,7 +945,7 @@ pdf_dict_put(pdf_obj *obj, pdf_obj *key, pdf_obj *val)
void
pdf_dict_puts(pdf_obj *obj, char *key, pdf_obj *val)
{
- pdf_obj *keyobj = fz_new_name(obj->ctx, key);
+ pdf_obj *keyobj = pdf_new_name(obj->ctx, key);
pdf_dict_put(obj, keyobj, val);
pdf_drop_obj(keyobj);
}
diff --git a/pdf/pdf_parse.c b/pdf/pdf_parse.c
index 4a7e421f..ed7889ed 100644
--- a/pdf/pdf_parse.c
+++ b/pdf/pdf_parse.c
@@ -196,7 +196,7 @@ pdf_obj *
pdf_to_utf8_name(pdf_document *xref, pdf_obj *src)
{
char *buf = pdf_to_utf8(xref, src);
- pdf_obj *dst = fz_new_name(xref->ctx, buf);
+ pdf_obj *dst = pdf_new_name(xref->ctx, buf);
fz_free(xref->ctx, buf);
return dst;
}
@@ -289,7 +289,7 @@ pdf_parse_array(pdf_document *xref, fz_stream *file, pdf_lexbuf *buf)
break;
case PDF_TOK_NAME:
- obj = fz_new_name(ctx, buf->scratch);
+ obj = pdf_new_name(ctx, buf->scratch);
pdf_array_push(ary, obj);
pdf_drop_obj(obj);
obj = NULL;
@@ -372,7 +372,7 @@ pdf_parse_dict(pdf_document *xref, fz_stream *file, pdf_lexbuf *buf)
if (tok != PDF_TOK_NAME)
fz_throw(ctx, "invalid key in dict");
- key = fz_new_name(ctx, buf->scratch);
+ key = pdf_new_name(ctx, buf->scratch);
tok = pdf_lex(file, buf);
@@ -386,7 +386,7 @@ pdf_parse_dict(pdf_document *xref, fz_stream *file, pdf_lexbuf *buf)
val = pdf_parse_dict(xref, file, buf);
break;
- case PDF_TOK_NAME: val = fz_new_name(ctx, buf->scratch); break;
+ case PDF_TOK_NAME: val = pdf_new_name(ctx, buf->scratch); break;
case PDF_TOK_REAL: val = pdf_new_real(ctx, buf->f); break;
case PDF_TOK_STRING: val = pdf_new_string(ctx, buf->scratch, buf->len); break;
case PDF_TOK_TRUE: val = pdf_new_bool(ctx, 1); break;
@@ -455,7 +455,7 @@ pdf_parse_stm_obj(pdf_document *xref, fz_stream *file, pdf_lexbuf *buf)
return pdf_parse_array(xref, file, buf);
case PDF_TOK_OPEN_DICT:
return pdf_parse_dict(xref, file, buf);
- case PDF_TOK_NAME: return fz_new_name(ctx, buf->scratch); break;
+ case PDF_TOK_NAME: return pdf_new_name(ctx, buf->scratch); break;
case PDF_TOK_REAL: return pdf_new_real(ctx, buf->f); break;
case PDF_TOK_STRING: return pdf_new_string(ctx, buf->scratch, buf->len); break;
case PDF_TOK_TRUE: return pdf_new_bool(ctx, 1); break;
@@ -506,7 +506,7 @@ pdf_parse_ind_obj(pdf_document *xref,
obj = pdf_parse_dict(xref, file, buf);
break;
- case PDF_TOK_NAME: obj = fz_new_name(ctx, buf->scratch); break;
+ case PDF_TOK_NAME: obj = pdf_new_name(ctx, buf->scratch); break;
case PDF_TOK_REAL: obj = pdf_new_real(ctx, buf->f); break;
case PDF_TOK_STRING: obj = pdf_new_string(ctx, buf->scratch, buf->len); break;
case PDF_TOK_TRUE: obj = pdf_new_bool(ctx, 1); break;
diff --git a/pdf/pdf_write.c b/pdf/pdf_write.c
index 5d03ffe3..24d328d6 100644
--- a/pdf/pdf_write.c
+++ b/pdf/pdf_write.c
@@ -1054,7 +1054,7 @@ add_linearization_objs(pdf_document *xref, pdf_write_options *opts)
/* FIXME: Do we have document information? Do an I entry */
/* FIXME: Do we have logical structure heirarchy? Do a C entry */
/* FIXME: Do L, Page Label hint table */
- o = fz_new_name(ctx, "FlateDecode");
+ o = pdf_new_name(ctx, "FlateDecode");
pdf_dict_puts(hint_obj, "Filter", o);
pdf_drop_obj(o);
o = NULL;
@@ -1426,7 +1426,7 @@ static void addhexfilter(pdf_document *xref, pdf_obj *dict)
pdf_obj *ahx, *nullobj;
fz_context *ctx = xref->ctx;
- ahx = fz_new_name(ctx, "ASCIIHexDecode");
+ ahx = pdf_new_name(ctx, "ASCIIHexDecode");
nullobj = pdf_new_null(ctx);
newf = newdp = NULL;
diff --git a/pdf/pdf_xobject.c b/pdf/pdf_xobject.c
index afa86527..19de0363 100644
--- a/pdf/pdf_xobject.c
+++ b/pdf/pdf_xobject.c
@@ -153,11 +153,11 @@ pdf_new_xobject(pdf_document *xref, fz_rect *bbox, fz_matrix *mat)
res = pdf_new_dict(ctx, 0);
procset = pdf_new_array(ctx, 2);
- obj = fz_new_name(ctx, "PDF");
+ obj = pdf_new_name(ctx, "PDF");
pdf_array_push(procset, obj);
pdf_drop_obj(obj);
obj = NULL;
- obj = fz_new_name(ctx, "Text");
+ obj = pdf_new_name(ctx, "Text");
pdf_array_push(procset, obj);
pdf_drop_obj(obj);
obj = NULL;
@@ -166,12 +166,12 @@ pdf_new_xobject(pdf_document *xref, fz_rect *bbox, fz_matrix *mat)
procset = NULL;
pdf_dict_puts(dict, "Resources", res);
- obj = fz_new_name(ctx, "Form");
+ obj = pdf_new_name(ctx, "Form");
pdf_dict_puts(dict, "Subtype", obj);
pdf_drop_obj(obj);
obj = NULL;
- obj = fz_new_name(ctx, "XObject");
+ obj = pdf_new_name(ctx, "XObject");
pdf_dict_puts(dict, "Type", obj);
pdf_drop_obj(obj);
obj = NULL;