diff options
-rw-r--r-- | platform/android/build.gradle | 2 | ||||
-rw-r--r-- | platform/android/jni/mupdf.c | 10 | ||||
-rw-r--r-- | platform/android/res/drawable-mdpi/ic_proof.png | bin | 1244 -> 2267 bytes | |||
-rw-r--r-- | platform/android/res/drawable-mdpi/ic_sep.png | bin | 0 -> 1098 bytes | |||
-rw-r--r-- | platform/android/res/layout/buttons.xml | 12 | ||||
-rw-r--r-- | platform/android/res/values/strings.xml | 1 | ||||
-rw-r--r-- | platform/android/src/com/artifex/mupdfdemo/MuPDFActivity.java | 292 | ||||
-rw-r--r-- | platform/android/src/com/artifex/mupdfdemo/MuPDFCore.java | 20 | ||||
-rw-r--r-- | source/gprf/gprf-doc.c | 2 |
9 files changed, 304 insertions, 35 deletions
diff --git a/platform/android/build.gradle b/platform/android/build.gradle index 85e0d1dd..2feb577f 100644 --- a/platform/android/build.gradle +++ b/platform/android/build.gradle @@ -68,7 +68,7 @@ if (Os.isFamily(Os.FAMILY_WINDOWS)) { /* This task builds the native part */ task buildNative(type: Exec,description: 'Compile JNI source via NDK') { println('executing buildNative') - commandLine ndkBuildPath, '-C', file('.').absolutePath + commandLine ndkBuildPath, '-C', file('.').absolutePath, ' SUPPORT_GPROOF=1' //'NDK_PROJECT_PATH=build','APP_BUILD_SCRIPT=src/main/jni/Android.mk'//force using appropriate Makefile } diff --git a/platform/android/jni/mupdf.c b/platform/android/jni/mupdf.c index 96b9162d..d28b7792 100644 --- a/platform/android/jni/mupdf.c +++ b/platform/android/jni/mupdf.c @@ -2722,7 +2722,7 @@ static char *tmp_gproof_path(char *path) } JNIEXPORT jstring JNICALL -JNI_FN(MuPDFCore_startProofInternal)(JNIEnv * env, jobject thiz) +JNI_FN(MuPDFCore_startProofInternal)(JNIEnv * env, jobject thiz, int inResolution) { #ifdef SUPPORT_GPROOF globals *glo = get_globals(env, thiz); @@ -2737,9 +2737,13 @@ JNI_FN(MuPDFCore_startProofInternal)(JNIEnv * env, jobject thiz) if (!tmp) return NULL; + int theResolution = PROOF_RESOLUTION; + if (inResolution != 0) + theResolution = inResolution; + fz_try(ctx) { - fz_write_gproof_file(ctx, glo->current_path, glo->doc, tmp, PROOF_RESOLUTION); + fz_write_gproof_file(ctx, glo->current_path, glo->doc, tmp, theResolution, "", ""); LOGE("Creating %s\n", tmp); ret = (*env)->NewStringUTF(env, tmp); @@ -2851,7 +2855,7 @@ JNI_FN(MuPDFCore_getSepInternal)(JNIEnv *env, jobject thiz, int page, int sep) return NULL; /* MuPDF returns RGBA as bytes. Android wants a packed BGRA int. */ - name = fz_get_separation_on_page(ctx, glo->pages[i].page, sep, &rgba[0], &cmyk); + name = fz_get_separation_on_page(ctx, glo->pages[i].page, sep, (unsigned int *)(&rgba[0]), &cmyk); bgra = (rgba[0] << 16) | (rgba[1]<<8) | rgba[2] | (rgba[3]<<24); jname = name ? (*env)->NewStringUTF(env, name) : NULL; diff --git a/platform/android/res/drawable-mdpi/ic_proof.png b/platform/android/res/drawable-mdpi/ic_proof.png Binary files differindex 61d94587..cbda8721 100644 --- a/platform/android/res/drawable-mdpi/ic_proof.png +++ b/platform/android/res/drawable-mdpi/ic_proof.png diff --git a/platform/android/res/drawable-mdpi/ic_sep.png b/platform/android/res/drawable-mdpi/ic_sep.png Binary files differnew file mode 100644 index 00000000..2167be2e --- /dev/null +++ b/platform/android/res/drawable-mdpi/ic_sep.png diff --git a/platform/android/res/layout/buttons.xml b/platform/android/res/layout/buttons.xml index 12de40c6..6c1620ba 100644 --- a/platform/android/res/layout/buttons.xml +++ b/platform/android/res/layout/buttons.xml @@ -31,6 +31,17 @@ android:textAppearance="?android:attr/textAppearanceMedium" /> <ImageButton + android:id="@+id/sepsButton" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_centerVertical="true" + android:layout_alignParentRight="true" + android:contentDescription="Separations" + android:background="@drawable/button" + android:onClick="OnSepsButtonClick" + android:src="@drawable/ic_sep" /> + + <ImageButton android:id="@+id/linkButton" android:layout_width="wrap_content" android:layout_height="wrap_content" @@ -393,4 +404,5 @@ android:background="@drawable/page_num" android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="#FFFFFF" /> + </RelativeLayout> diff --git a/platform/android/res/values/strings.xml b/platform/android/res/values/strings.xml index dcff35f4..ab4b7152 100644 --- a/platform/android/res/values/strings.xml +++ b/platform/android/res/values/strings.xml @@ -26,6 +26,7 @@ <string name="ink">Ink</string> <string name="save">Save</string> <string name="proof">Proof</string> + <string name="separation">Separation</string> <string name="print">Print</string> <string name="dismiss">Dismiss</string> <string name="parent_directory">[Up one level]</string> diff --git a/platform/android/src/com/artifex/mupdfdemo/MuPDFActivity.java b/platform/android/src/com/artifex/mupdfdemo/MuPDFActivity.java index 7b4a6040..91b1e8fe 100644 --- a/platform/android/src/com/artifex/mupdfdemo/MuPDFActivity.java +++ b/platform/android/src/com/artifex/mupdfdemo/MuPDFActivity.java @@ -1,10 +1,5 @@ package com.artifex.mupdfdemo; -import java.io.InputStream; -import java.util.concurrent.Executor; - -import com.artifex.mupdfdemo.ReaderView.ViewMapper; - import android.app.Activity; import android.app.AlertDialog; import android.content.Context; @@ -15,6 +10,9 @@ import android.content.SharedPreferences; import android.content.res.Resources; import android.database.Cursor; import android.graphics.Color; +import android.graphics.Rect; +import android.graphics.drawable.ShapeDrawable; +import android.graphics.drawable.shapes.RectShape; import android.net.Uri; import android.os.Bundle; import android.os.Handler; @@ -23,6 +21,8 @@ import android.text.TextWatcher; import android.text.method.PasswordTransformationMethod; import android.view.KeyEvent; import android.view.Menu; +import android.view.MenuItem; +import android.view.MenuItem.OnMenuItemClickListener; import android.view.View; import android.view.animation.Animation; import android.view.animation.TranslateAnimation; @@ -30,11 +30,17 @@ import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.ImageButton; +import android.widget.PopupMenu; import android.widget.RelativeLayout; import android.widget.SeekBar; import android.widget.TextView; import android.widget.ViewAnimator; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.concurrent.Executor; + class ThreadPerTaskExecutor implements Executor { public void execute(Runnable r) { new Thread(r).start(); @@ -77,6 +83,7 @@ public class MuPDFActivity extends Activity implements FilePicker.FilePickerSupp private EditText mSearchText; private SearchTask mSearchTask; private ImageButton mProofButton; + private ImageButton mSepsButton; private AlertDialog.Builder mAlertBuilder; private boolean mLinkHighlight = false; private final Handler mHandler = new Handler(); @@ -85,7 +92,8 @@ public class MuPDFActivity extends Activity implements FilePicker.FilePickerSupp private AsyncTask<Void,Void,MuPDFAlert> mAlertTask; private AlertDialog mAlertDialog; private FilePicker mFilePicker; - private String mProofFile; + private String mProofFile; + private boolean mSepEnabled[][]; static private AlertDialog.Builder gAlertBuilder; static public AlertDialog.Builder getAlertBuilder() {return gAlertBuilder;} @@ -214,7 +222,7 @@ public class MuPDFActivity extends Activity implements FilePicker.FilePickerSupp mFileName = new String(lastSlashPos == -1 ? path : path.substring(lastSlashPos+1)); - System.out.println("Trying to open "+path); + System.out.println("Trying to open " + path); try { core = new MuPDFCore(this, path); @@ -252,6 +260,13 @@ public class MuPDFActivity extends Activity implements FilePicker.FilePickerSupp return core; } + // determine whether the current activity is a proofing activity. + public boolean isProofing() + { + String format = core.fileFormat(); + return (format.equals("GPROOF")); + } + /** Called when the activity is first created. */ @Override public void onCreate(final Bundle savedInstanceState) @@ -271,6 +286,7 @@ public class MuPDFActivity extends Activity implements FilePicker.FilePickerSupp if (core == null) { Intent intent = getIntent(); byte buffer[] = null; + if (Intent.ACTION_VIEW.equals(intent.getAction())) { Uri uri = intent.getData(); System.out.println("URI to open is: " + uri); @@ -369,6 +385,32 @@ public class MuPDFActivity extends Activity implements FilePicker.FilePickerSupp } createUI(savedInstanceState); + + // hide the proof button if this file can't be proofed + if (!core.canProof()) { + mProofButton.setVisibility(View.INVISIBLE); + } + + if (isProofing()) { + + // start the activity with a new array + mSepEnabled = null; + + // show the separations button + mSepsButton.setVisibility(View.VISIBLE); + + // hide some other buttons + mLinkButton.setVisibility(View.INVISIBLE); + mReflowButton.setVisibility(View.INVISIBLE); + mOutlineButton.setVisibility(View.INVISIBLE); + mSearchButton.setVisibility(View.INVISIBLE); + mMoreButton.setVisibility(View.INVISIBLE); + } + else { + // hide the separations button + mSepsButton.setVisibility(View.INVISIBLE); + } + } public void requestPassword(final Bundle savedInstanceState) { @@ -381,14 +423,14 @@ public class MuPDFActivity extends Activity implements FilePicker.FilePickerSupp alert.setView(mPasswordView); alert.setButton(AlertDialog.BUTTON_POSITIVE, getString(R.string.okay), new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) { - if (core.authenticatePassword(mPasswordView.getText().toString())) { - createUI(savedInstanceState); - } else { - requestPassword(savedInstanceState); - } - } - }); + public void onClick(DialogInterface dialog, int which) { + if (core.authenticatePassword(mPasswordView.getText().toString())) { + createUI(savedInstanceState); + } else { + requestPassword(savedInstanceState); + } + } + }); alert.setButton(AlertDialog.BUTTON_NEGATIVE, getString(R.string.cancel), new DialogInterface.OnClickListener() { @@ -410,6 +452,7 @@ public class MuPDFActivity extends Activity implements FilePicker.FilePickerSupp protected void onMoveToChild(int i) { if (core == null) return; + mPageNumberView.setText(String.format("%d / %d", i + 1, core.countPages())); mPageSlider.setMax((core.countPages() - 1) * mPageSliderRes); @@ -618,6 +661,13 @@ public class MuPDFActivity extends Activity implements FilePicker.FilePickerSupp layout.addView(mDocView); layout.addView(mButtonsView); setContentView(layout); + + if (isProofing()) { + // go to the current page + int currentPage = getIntent().getIntExtra("startingPage", 0); + mDocView.setDisplayedViewIndex(currentPage); + } + } @Override @@ -635,12 +685,19 @@ public class MuPDFActivity extends Activity implements FilePicker.FilePickerSupp if (mFilePicker != null && resultCode == RESULT_OK) mFilePicker.onPick(data.getData()); case PROOF_REQUEST: + // we're returning from a proofing activity + if (mProofFile != null) { core.endProof(mProofFile); mProofFile = null; } + + // return the top bar to default + mTopBarMode = TopBarMode.Main; + mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal()); } + super.onActivityResult(requestCode, resultCode, data); } @@ -732,7 +789,7 @@ public class MuPDFActivity extends Activity implements FilePicker.FilePickerSupp private void setButtonEnabled(ImageButton button, boolean enabled) { button.setEnabled(enabled); - button.setColorFilter(enabled ? Color.argb(255, 255, 255, 255):Color.argb(255, 128, 128, 128)); + button.setColorFilter(enabled ? Color.argb(255, 255, 255, 255) : Color.argb(255, 128, 128, 128)); } private void setLinkHighlight(boolean highlight) { @@ -752,7 +809,7 @@ public class MuPDFActivity extends Activity implements FilePicker.FilePickerSupp int index = mDocView.getDisplayedViewIndex(); updatePageNumView(index); mPageSlider.setMax((core.countPages()-1)*mPageSliderRes); - mPageSlider.setProgress(index*mPageSliderRes); + mPageSlider.setProgress(index * mPageSliderRes); if (mTopBarMode == TopBarMode.Search) { mSearchText.requestFocus(); showKeyboard(); @@ -840,7 +897,7 @@ public class MuPDFActivity extends Activity implements FilePicker.FilePickerSupp private void updatePageNumView(int index) { if (core == null) return; - mPageNumberView.setText(String.format("%d / %d", index+1, core.countPages())); + mPageNumberView.setText(String.format("%d / %d", index + 1, core.countPages())); } private void printDoc() { @@ -899,13 +956,16 @@ public class MuPDFActivity extends Activity implements FilePicker.FilePickerSupp mLinkButton = (ImageButton)mButtonsView.findViewById(R.id.linkButton); mMoreButton = (ImageButton)mButtonsView.findViewById(R.id.moreButton); mProofButton = (ImageButton)mButtonsView.findViewById(R.id.proofButton); + mSepsButton = (ImageButton)mButtonsView.findViewById(R.id.sepsButton); mTopBarSwitcher.setVisibility(View.INVISIBLE); mPageNumberView.setVisibility(View.INVISIBLE); mInfoView.setVisibility(View.INVISIBLE); + mPageSlider.setVisibility(View.INVISIBLE); if (!core.gprfSupported()) { mProofButton.setVisibility(View.INVISIBLE); } + mSepsButton.setVisibility(View.INVISIBLE); } public void OnMoreButtonClick(View v) { @@ -922,15 +982,204 @@ public class MuPDFActivity extends Activity implements FilePicker.FilePickerSupp printDoc(); } - public void OnProofButtonClick(View v) { - mProofFile = core.startProof(); + // start a proof activity with the given resolution. + public void proofWithResolution (int resolution) + { + mProofFile = core.startProof(resolution); Uri uri = Uri.parse("file://"+mProofFile); - Intent intent = new Intent(this,MuPDFActivity.class); + Intent intent = new Intent(this, MuPDFActivity.class); intent.setAction(Intent.ACTION_VIEW); intent.setData(uri); + // add the current page so it can be found when the activity is running + intent.putExtra("startingPage", mDocView.getDisplayedViewIndex()); startActivityForResult(intent, PROOF_REQUEST); } + public void OnProofButtonClick(final View v) + { + // set up the menu or resolutions. + final PopupMenu popup = new PopupMenu(this, v); + popup.getMenu().add(0, 1, 0, "Select a resolution:"); + popup.getMenu().add(0, 72, 0, "72"); + popup.getMenu().add(0, 96, 0, "96"); + popup.getMenu().add(0, 150, 0, "150"); + popup.getMenu().add(0, 300, 0, "300"); + popup.getMenu().add(0, 600, 0, "600"); + popup.getMenu().add(0, 1200, 0, "1200"); + popup.getMenu().add(0, 2400, 0, "2400"); + + // prevent the first item from being dismissed. + // is there not a better way to do this? It requires minimum API 14 + MenuItem item = popup.getMenu().getItem(0); + item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW); + item.setActionView(new View(v.getContext())); + item.setOnActionExpandListener(new MenuItem.OnActionExpandListener() { + @Override + public boolean onMenuItemActionExpand(MenuItem item) { + return false; + } + + @Override + public boolean onMenuItemActionCollapse(MenuItem item) { + return false; + } + }); + + popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + int id = item.getItemId(); + if (id != 1) { + // it's a resolution. The id is also the resolution value + proofWithResolution(id); + return true; + } + return false; + } + }); + + popup.show(); + } + + public void OnSepsButtonClick(final View v) + { + if (isProofing()) { + + // get the current page + final int currentPage = mDocView.getDisplayedViewIndex(); + + // buid a popup menu based on the given separations + final PopupMenu menu = new PopupMenu(this, v); + + // This makes the popup menu display icons, which by default it does not do. + // I worry that this relies on the internals of PopupMenu, which could change. + try { + Field[] fields = menu.getClass().getDeclaredFields(); + for (Field field : fields) { + if ("mPopup".equals(field.getName())) { + field.setAccessible(true); + Object menuPopupHelper = field.get(menu); + Class<?> classPopupHelper = Class.forName(menuPopupHelper + .getClass().getName()); + Method setForceIcons = classPopupHelper.getMethod( + "setForceShowIcon", boolean.class); + setForceIcons.invoke(menuPopupHelper, true); + break; + } + } + } catch (Exception e) { + e.printStackTrace(); + } + + // get the maximum number of seps on any page. + // We use this to dimension an array further down + int maxSeps = 0; + int numPages = core.countPages(); + for (int page=0; page<numPages; page++) { + int numSeps = core.getNumSepsOnPage(page); + if (numSeps>maxSeps) + maxSeps = numSeps; + } + + // if this is the first time, create the "enabled" array + if (mSepEnabled==null) { + mSepEnabled = new boolean[numPages][maxSeps]; + for (int page=0; page<numPages; page++) { + for (int i = 0; i < maxSeps; i++) + mSepEnabled[page][i] = true; + } + } + + // count the seps on this page + int numSeps = core.getNumSepsOnPage(currentPage); + + // for each sep, + for (int i = 0; i < numSeps; i++) { + +// // Robin use this to skip separations +// if (i==12) +// break; + + // get the name + Separation sep = core.getSep(currentPage,i); + String name = sep.name; + + // make a checkable menu item with that name + // and the separation index as the id + MenuItem item = menu.getMenu().add(0, i, 0, name+" "); + item.setCheckable(true); + + // set an icon that's the right color + int iconSize = 48; + int alpha = (sep.rgba >> 24) & 0xFF; + int red = (sep.rgba >> 16) & 0xFF; + int green = (sep.rgba >> 8 ) & 0xFF; + int blue = (sep.rgba >> 0 ) & 0xFF; + int color = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0); + + ShapeDrawable swatch = new ShapeDrawable (new RectShape()); + swatch.setIntrinsicHeight(iconSize); + swatch.setIntrinsicWidth(iconSize); + swatch.setBounds(new Rect(0, 0, iconSize, iconSize)); + swatch.getPaint().setColor(color); + item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); + item.setIcon(swatch); + + // check it (or not) + item.setChecked(mSepEnabled[currentPage][i]); + + // establishing a menu item listener + item.setOnMenuItemClickListener(new OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + // someone tapped a menu item. get the ID + int sep = item.getItemId(); + + // toggle the sep + mSepEnabled[currentPage][sep] = !mSepEnabled[currentPage][sep]; + item.setChecked(mSepEnabled[currentPage][sep]); + core.controlSepOnPage(currentPage, sep, !mSepEnabled[currentPage][sep]); + + // prevent the menu from being dismissed by these items + item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW); + item.setActionView(new View(v.getContext())); + item.setOnActionExpandListener(new MenuItem.OnActionExpandListener() { + @Override + public boolean onMenuItemActionExpand(MenuItem item) { + return false; + } + + @Override + public boolean onMenuItemActionCollapse(MenuItem item) { + return false; + } + }); + return false; + } + }); + + // tell core to enable or disable each sep as appropriate + // but don't refresh the page yet. + core.controlSepOnPage(currentPage, i, !mSepEnabled[currentPage][i]); + } + + // add one for done + MenuItem itemDone = menu.getMenu().add(0, 0, 0, "Done"); + itemDone.setOnMenuItemClickListener(new OnMenuItemClickListener() { + @Override + public boolean onMenuItemClick(MenuItem item) { + // refresh the view + mDocView.refresh(false); + return true; + } + }); + + // show the menu + menu.show(); + } + + } + public void OnCopyTextButtonClick(View v) { mTopBarMode = TopBarMode.Accept; mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal()); @@ -1164,4 +1413,5 @@ public class MuPDFActivity extends Activity implements FilePicker.FilePickerSupp intent.setAction(ChoosePDFActivity.PICK_KEY_FILE); startActivityForResult(intent, FILEPICK_REQUEST); } + } diff --git a/platform/android/src/com/artifex/mupdfdemo/MuPDFCore.java b/platform/android/src/com/artifex/mupdfdemo/MuPDFCore.java index 53b9d565..de202b3c 100644 --- a/platform/android/src/com/artifex/mupdfdemo/MuPDFCore.java +++ b/platform/android/src/com/artifex/mupdfdemo/MuPDFCore.java @@ -1,12 +1,10 @@ package com.artifex.mupdfdemo; -import java.util.ArrayList; - import android.content.Context; import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; import android.graphics.PointF; import android.graphics.RectF; -import android.content.Intent; + +import java.util.ArrayList; public class MuPDFCore { @@ -90,7 +88,8 @@ public class MuPDFCore private native long createCookie(); private native void destroyCookie(long cookie); private native void abortCookie(long cookie); - private native String startProofInternal(); + + private native String startProofInternal(int resolution); private native void endProofInternal(String filename); private native int getNumSepsOnPageInternal(int page); private native int controlSepOnPageInternal(int page, int sep, boolean disable); @@ -365,8 +364,8 @@ public class MuPDFCore saveInternal(); } - public synchronized String startProof() { - return startProofInternal(); + public synchronized String startProof(int resolution) { + return startProofInternal(resolution); } public synchronized void endProof(String filename) { @@ -379,9 +378,12 @@ public class MuPDFCore return gprfSupportedInternal(); } - public static boolean isProofing() + public boolean canProof() { - return mIsProofing; + String format = fileFormat(); + if (format.contains("PDF")) + return true; + return false; } public synchronized int getNumSepsOnPage(int page) { diff --git a/source/gprf/gprf-doc.c b/source/gprf/gprf-doc.c index b4777c6c..944d5d70 100644 --- a/source/gprf/gprf-doc.c +++ b/source/gprf/gprf-doc.c @@ -9,7 +9,7 @@ #endif #include "mupdf/fitz.h" -#ifdef USE_GS_API +#if defined(USE_GS_API) && !defined(__ANDROID__) #include "iapi.h" #endif |