diff options
author | Paul Gardiner <paulg.artifex@glidos.net> | 2013-03-25 12:59:54 +0000 |
---|---|---|
committer | Paul Gardiner <paulg.artifex@glidos.net> | 2013-03-25 12:59:54 +0000 |
commit | 199abe0069381d79fc34c86268e408083ad18397 (patch) | |
tree | 0dbefb3a08a5d44dae2d5e98635241a7224b231d /android/src/com | |
parent | 41f10c71dbae05fb538f51a495ef7aaa1861fd5d (diff) | |
download | mupdf-199abe0069381d79fc34c86268e408083ad18397.tar.xz |
Android: add support for Ink annotation creation
Diffstat (limited to 'android/src/com')
7 files changed, 204 insertions, 7 deletions
diff --git a/android/src/com/artifex/mupdfdemo/MuPDFActivity.java b/android/src/com/artifex/mupdfdemo/MuPDFActivity.java index 01783ede..90e55887 100644 --- a/android/src/com/artifex/mupdfdemo/MuPDFActivity.java +++ b/android/src/com/artifex/mupdfdemo/MuPDFActivity.java @@ -28,6 +28,7 @@ import android.view.animation.Animation; import android.view.animation.TranslateAnimation; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; +import android.widget.Button; import android.widget.EditText; import android.widget.ImageButton; import android.widget.RelativeLayout; @@ -44,7 +45,7 @@ class ThreadPerTaskExecutor implements Executor { public class MuPDFActivity extends Activity { /* The core rendering instance */ - enum TopBarMode {Main, Search, Text, Annotation}; + enum TopBarMode {Main, Search, Text, AnnotSelect, AnnotCreate, InkCreate}; private MuPDFCore core; private String mFileName; @@ -68,6 +69,12 @@ public class MuPDFActivity extends Activity private ImageButton mCancelButton; private ImageButton mOutlineButton; private ImageButton mDeleteButton; + private ImageButton mCancelDeleteButton; + private ImageButton mAnnotButton; + private ImageButton mCancelAnnotButton; + private ImageButton mInkButton; + private Button mSaveInkButton; + private ImageButton mCancelInkButton; private ViewAnimator mTopBarSwitcher; private ImageButton mLinkButton; private TopBarMode mTopBarMode; @@ -402,12 +409,12 @@ public class MuPDFActivity extends Activity switch (item) { case Annotation: showButtons(); - mTopBarMode = TopBarMode.Annotation; + mTopBarMode = TopBarMode.AnnotSelect; mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal()); break; case Widget: case Nothing: - if (mTopBarMode == TopBarMode.Annotation) { + if (mTopBarMode == TopBarMode.AnnotSelect) { mTopBarMode = TopBarMode.Main; mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal()); } @@ -468,6 +475,13 @@ public class MuPDFActivity extends Activity } }); + mAnnotButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + mTopBarMode = TopBarMode.AnnotCreate; + mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal()); + } + }); + // Activate the select button mSelectButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { @@ -483,6 +497,58 @@ public class MuPDFActivity extends Activity if (pageView != null) pageView.deselectText(); mDocView.setMode(MuPDFReaderView.Mode.Viewing); + mTopBarMode = TopBarMode.AnnotCreate; + mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal()); + } + }); + + mInkButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + mDocView.setMode(MuPDFReaderView.Mode.Drawing); + mTopBarMode = TopBarMode.InkCreate; + mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal()); + } + }); + + mCancelInkButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + MuPDFView pageView = (MuPDFView) mDocView.getDisplayedView(); + if (pageView != null) + pageView.cancelDraw(); + mDocView.setMode(MuPDFReaderView.Mode.Viewing); + mTopBarMode = TopBarMode.AnnotCreate; + mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal()); + } + }); + + mSaveInkButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + MuPDFView pageView = (MuPDFView) mDocView.getDisplayedView(); + if (pageView != null) + pageView.saveDraw(); + mDocView.setMode(MuPDFReaderView.Mode.Viewing); + mTopBarMode = TopBarMode.Main; + mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal()); + } + }); + + mCancelDeleteButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + MuPDFView pageView = (MuPDFView) mDocView.getDisplayedView(); + if (pageView != null) + pageView.deselectAnnotation(); + mDocView.setMode(MuPDFReaderView.Mode.Viewing); + mTopBarMode = TopBarMode.Main; + mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal()); + } + }); + + mCancelAnnotButton.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + MuPDFView pageView = (MuPDFView) mDocView.getDisplayedView(); + if (pageView != null) + pageView.deselectText(); + mDocView.setMode(MuPDFReaderView.Mode.Viewing); mTopBarMode = TopBarMode.Main; mTopBarSwitcher.setDisplayedChild(mTopBarMode.ordinal()); } @@ -897,6 +963,12 @@ public class MuPDFActivity extends Activity mCancelButton = (ImageButton)mButtonsView.findViewById(R.id.cancel); mOutlineButton = (ImageButton)mButtonsView.findViewById(R.id.outlineButton); mDeleteButton = (ImageButton)mButtonsView.findViewById(R.id.deleteButton); + mCancelDeleteButton = (ImageButton)mButtonsView.findViewById(R.id.cancelDeleteButton); + mAnnotButton = (ImageButton)mButtonsView.findViewById(R.id.annotButton); + mCancelAnnotButton = (ImageButton)mButtonsView.findViewById(R.id.cancelAnnotButton); + mInkButton = (ImageButton)mButtonsView.findViewById(R.id.inkButton); + mSaveInkButton = (Button)mButtonsView.findViewById(R.id.saveInkButton); + mCancelInkButton = (ImageButton)mButtonsView.findViewById(R.id.cancelInkButton); mTopBarSwitcher = (ViewAnimator)mButtonsView.findViewById(R.id.switcher); mSearchBack = (ImageButton)mButtonsView.findViewById(R.id.searchBack); mSearchFwd = (ImageButton)mButtonsView.findViewById(R.id.searchForward); diff --git a/android/src/com/artifex/mupdfdemo/MuPDFCore.java b/android/src/com/artifex/mupdfdemo/MuPDFCore.java index 424e3536..2443784a 100644 --- a/android/src/com/artifex/mupdfdemo/MuPDFCore.java +++ b/android/src/com/artifex/mupdfdemo/MuPDFCore.java @@ -40,6 +40,7 @@ public class MuPDFCore private native TextChar[][][][] text(); private native byte[] textAsHtml(); private native void addMarkupAnnotationInternal(PointF[] quadPoints, int type); + private native void addInkAnnotationInternal(PointF[][] arcs); private native void deleteAnnotationInternal(int annot_index); private native int passClickEventInternal(int page, float x, float y); private native void setFocusedWidgetChoiceSelectedInternal(String [] selected); @@ -253,6 +254,11 @@ public class MuPDFCore addMarkupAnnotationInternal(quadPoints, type.ordinal()); } + public synchronized void addInkAnnotation(int page, PointF[][] arcs) { + gotoPage(page); + addInkAnnotationInternal(arcs); + } + public synchronized void deleteAnnotation(int page, int annot_index) { gotoPage(page); deleteAnnotationInternal(annot_index); diff --git a/android/src/com/artifex/mupdfdemo/MuPDFPageView.java b/android/src/com/artifex/mupdfdemo/MuPDFPageView.java index 06c3827a..69f038bb 100644 --- a/android/src/com/artifex/mupdfdemo/MuPDFPageView.java +++ b/android/src/com/artifex/mupdfdemo/MuPDFPageView.java @@ -59,8 +59,6 @@ class PassClickResultChoice extends PassClickResult { } public class MuPDFPageView extends PageView implements MuPDFView { - private static final float LINE_THICKNESS = 0.07f; - private static final float STRIKE_HEIGHT = 0.375f; private final MuPDFCore mCore; private AsyncTask<Void,Void,PassClickResult> mPassClick; private RectF mWidgetAreas[]; @@ -75,6 +73,7 @@ public class MuPDFPageView extends PageView implements MuPDFView { private AsyncTask<String,Void,Boolean> mSetWidgetText; private AsyncTask<String,Void,Void> mSetWidgetChoice; private AsyncTask<PointF[],Void,Void> mAddStrikeOut; + private AsyncTask<PointF[][],Void,Void> mAddInk; private AsyncTask<Integer,Void,Void> mDeleteAnnotation; private Runnable changeReporter; @@ -185,6 +184,7 @@ public class MuPDFPageView extends PageView implements MuPDFView { case UNDERLINE: case SQUIGGLY: case STRIKEOUT: + case INK: mSelectedAnnotationIndex = i; setItemSelectBox(mAnnotations[i]); return Hit.Annotation; @@ -357,6 +357,34 @@ public class MuPDFPageView extends PageView implements MuPDFView { setItemSelectBox(null); } + public void saveDraw() { + PointF[][] path = getDraw(); + + if (path != null) { + if (mAddInk != null) { + mAddInk.cancel(true); + mAddInk = null; + } + mAddInk = new AsyncTask<PointF[][],Void,Void>() { + @Override + protected Void doInBackground(PointF[][]... params) { + mCore.addInkAnnotation(mPageNumber, params[0]); + return null; + } + + @Override + protected void onPostExecute(Void result) { + loadAnnotations(); + update(); + } + + }; + + mAddInk.execute(getDraw()); + cancelDraw(); + } + } + @Override protected Bitmap drawPage(int sizeX, int sizeY, int patchX, int patchY, int patchWidth, int patchHeight) { diff --git a/android/src/com/artifex/mupdfdemo/MuPDFReaderView.java b/android/src/com/artifex/mupdfdemo/MuPDFReaderView.java index 6ddb69da..0aa1909b 100644 --- a/android/src/com/artifex/mupdfdemo/MuPDFReaderView.java +++ b/android/src/com/artifex/mupdfdemo/MuPDFReaderView.java @@ -95,15 +95,20 @@ public class MuPDFReaderView extends ReaderView { } @Override - public void onShowPress(MotionEvent e) { + public boolean onDown(MotionEvent e) { switch (mMode) { case Drawing: + MuPDFView pageView = (MuPDFView)getDisplayedView(); + if (pageView != null) + pageView.startDraw(e.getX(), e.getY()); break; } + return super.onDown(e); } public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + MuPDFView pageView = (MuPDFView)getDisplayedView(); switch (mMode) { case Viewing: if (!tapDisabled) @@ -111,11 +116,12 @@ public class MuPDFReaderView extends ReaderView { return super.onScroll(e1, e2, distanceX, distanceY); case Selecting: - MuPDFView pageView = (MuPDFView)getDisplayedView(); if (pageView != null) pageView.selectText(e1.getX(), e1.getY(), e2.getX(), e2.getY()); return true; case Drawing: + if (pageView != null) + pageView.continueDraw(e2.getX(), e2.getY()); return true; default: return true; diff --git a/android/src/com/artifex/mupdfdemo/MuPDFReflowView.java b/android/src/com/artifex/mupdfdemo/MuPDFReflowView.java index 1a2f1d91..9200982a 100644 --- a/android/src/com/artifex/mupdfdemo/MuPDFReflowView.java +++ b/android/src/com/artifex/mupdfdemo/MuPDFReflowView.java @@ -103,6 +103,18 @@ public class MuPDFReflowView extends WebView implements MuPDFView { return false; } + public void startDraw(float x, float y) { + } + + public void continueDraw(float x, float y) { + } + + public void cancelDraw() { + } + + public void saveDraw() { + } + public void setSearchBoxes(RectF[] searchBoxes) { } diff --git a/android/src/com/artifex/mupdfdemo/MuPDFView.java b/android/src/com/artifex/mupdfdemo/MuPDFView.java index 5f7f19e0..5731945d 100644 --- a/android/src/com/artifex/mupdfdemo/MuPDFView.java +++ b/android/src/com/artifex/mupdfdemo/MuPDFView.java @@ -20,6 +20,10 @@ public interface MuPDFView { public void setSearchBoxes(RectF searchBoxes[]); public void setLinkHighlighting(boolean f); public void deselectAnnotation(); + public void startDraw(float x, float y); + public void continueDraw(float x, float y); + public void cancelDraw(); + public void saveDraw(); public void setChangeReporter(Runnable reporter); public void update(); public void addHq(boolean update); diff --git a/android/src/com/artifex/mupdfdemo/PageView.java b/android/src/com/artifex/mupdfdemo/PageView.java index 3eb1e5a3..756ee2f5 100644 --- a/android/src/com/artifex/mupdfdemo/PageView.java +++ b/android/src/com/artifex/mupdfdemo/PageView.java @@ -7,6 +7,7 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; +import android.graphics.Path; import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; @@ -102,6 +103,8 @@ public abstract class PageView extends ViewGroup { private static final int HIGHLIGHT_COLOR = 0x802572AC; private static final int LINK_COLOR = 0x80AC7225; private static final int BOX_COLOR = 0xFF4444FF; + private static final int INK_COLOR = 0xFFFF0000; + private static final float INK_THICKNESS = 10.0f; private static final int BACKGROUND_COLOR = 0xFFFFFFFF; private static final int PROGRESS_DIALOG_DELAY = 200; protected final Context mContext; @@ -126,6 +129,7 @@ public abstract class PageView extends ViewGroup { private RectF mSelectBox; private TextWord mText[][]; private RectF mItemSelectBox; + protected ArrayList<ArrayList<PointF>> mDrawing; private View mSearchView; private boolean mIsBlank; private boolean mHighlightLinks; @@ -346,6 +350,28 @@ public abstract class PageView extends ViewGroup { paint.setColor(BOX_COLOR); canvas.drawRect(mItemSelectBox.left*scale, mItemSelectBox.top*scale, mItemSelectBox.right*scale, mItemSelectBox.bottom*scale, paint); } + + if (mDrawing != null) { + Path path = new Path(); + PointF p; + Iterator<ArrayList<PointF>> it = mDrawing.iterator(); + while (it.hasNext()) { + ArrayList<PointF> arc = it.next(); + if (arc.size() >= 2) { + Iterator<PointF> iit = arc.iterator(); + p = iit.next(); + path.moveTo(p.x*scale, p.y*scale); + while (iit.hasNext()) { + p = iit.next(); + path.lineTo(p.x*scale, p.y*scale); + } + } + } + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeWidth(INK_THICKNESS*scale); + paint.setColor(INK_COLOR); + canvas.drawPath(path, paint); + } } }; @@ -402,6 +428,49 @@ public abstract class PageView extends ViewGroup { } } + public void startDraw(float x, float y) { + float scale = mSourceScale*(float)getWidth()/(float)mSize.x; + float docRelX = (x - getLeft())/scale; + float docRelY = (y - getTop())/scale; + if (mDrawing == null) + mDrawing = new ArrayList<ArrayList<PointF>>(); + + ArrayList<PointF> arc = new ArrayList<PointF>(); + arc.add(new PointF(docRelX, docRelY)); + mDrawing.add(arc); + } + + public void continueDraw(float x, float y) { + float scale = mSourceScale*(float)getWidth()/(float)mSize.x; + float docRelX = (x - getLeft())/scale; + float docRelY = (y - getTop())/scale; + + if (mDrawing != null && mDrawing.size() > 0) { + ArrayList<PointF> arc = mDrawing.get(mDrawing.size() - 1); + arc.add(new PointF(docRelX, docRelY)); + mSearchView.invalidate(); + } + } + + public void cancelDraw() { + mDrawing = null; + mSearchView.invalidate(); + } + + protected PointF[][] getDraw() { + if (mDrawing == null) + return null; + + PointF[][] path = new PointF[mDrawing.size()][]; + + for (int i = 0; i < mDrawing.size(); i++) { + ArrayList<PointF> arc = mDrawing.get(i); + path[i] = arc.toArray(new PointF[arc.size()]); + } + + return path; + } + protected void processSelectedText(TextProcessor tp) { (new TextSelector(mText, mSelectBox)).select(tp); } |