diff options
author | Paul Gardiner <paulg.artifex@glidos.net> | 2012-08-29 10:58:09 +0100 |
---|---|---|
committer | Paul Gardiner <paulg.artifex@glidos.net> | 2012-08-29 10:58:09 +0100 |
commit | 6a5b8879b3b3b2a9ef085f38c1758d62456b921b (patch) | |
tree | f45fc1a9f32dcd31f335d27fffba75e4ceb9a23c | |
parent | d85ad485bb64508bc59cfd4977cb5a37cf882070 (diff) | |
parent | 25552e9f2ec3f17a0ce1cbd8d7818170d132959a (diff) | |
download | mupdf-6a5b8879b3b3b2a9ef085f38c1758d62456b921b.tar.xz |
Merge branch 'master' into forms
Conflicts:
cbz/mucbz.c
pdf/pdf_parse.c
pdf/pdf_form.c
xps/xps_zip.c
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; }; @@ -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 Binary files differnew file mode 100644 index 00000000..0ca9a6cc --- /dev/null +++ b/ios/x_alt_blue.png diff --git a/ios/x_alt_blue@2x.png b/ios/x_alt_blue@2x.png Binary files differnew file mode 100644 index 00000000..1cb67549 --- /dev/null +++ b/ios/x_alt_blue@2x.png 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; |