summaryrefslogtreecommitdiff
path: root/android
diff options
context:
space:
mode:
authorPaul Gardiner <paulg.artifex@glidos.net>2012-10-11 11:38:32 +0100
committerPaul Gardiner <paulg.artifex@glidos.net>2012-10-11 11:38:32 +0100
commit84f84d86e6d7f079e12139fa3306c3bc71713f77 (patch)
treec97062f75ed879cd3cb8b7e08a0fb63be23030b2 /android
parenteae647babea3730d2af1d1882707db355bd660ac (diff)
downloadmupdf-84f84d86e6d7f079e12139fa3306c3bc71713f77.tar.xz
Android Forms: pass in mouse events and handle updating
Also add a function to report whether the core has javascript support, so that the additional features can be enabled only when the javascript engine is present
Diffstat (limited to 'android')
-rw-r--r--android/jni/Core.mk1
-rw-r--r--android/jni/mupdf.c124
-rw-r--r--android/src/com/artifex/mupdf/MuPDFActivity.java38
-rw-r--r--android/src/com/artifex/mupdf/MuPDFCore.java42
-rw-r--r--android/src/com/artifex/mupdf/MuPDFPageView.java57
-rw-r--r--android/src/com/artifex/mupdf/PageView.java33
6 files changed, 260 insertions, 35 deletions
diff --git a/android/jni/Core.mk b/android/jni/Core.mk
index 202a8168..917b60b7 100644
--- a/android/jni/Core.mk
+++ b/android/jni/Core.mk
@@ -51,6 +51,7 @@ LOCAL_SRC_FILES := \
$(MY_ROOT)/fitz/doc_document.c \
$(MY_ROOT)/fitz/doc_link.c \
$(MY_ROOT)/fitz/doc_outline.c \
+ $(MY_ROOT)/fitz/doc_interactive.c \
$(MY_ROOT)/fitz/filt_basic.c \
$(MY_ROOT)/fitz/filt_dctd.c \
$(MY_ROOT)/fitz/filt_faxd.c \
diff --git a/android/jni/mupdf.c b/android/jni/mupdf.c
index 537c90c3..d4105115 100644
--- a/android/jni/mupdf.c
+++ b/android/jni/mupdf.c
@@ -101,11 +101,11 @@ Java_com_artifex_mupdf_MuPDFCore_gotoPageInternal(JNIEnv *env, jobject thiz, int
float zoom;
fz_matrix ctm;
fz_bbox bbox;
- fz_device *dev = NULL;
- fz_var(dev);
+ if (page == pagenum && currentPage != NULL)
+ return;
- if (currentPage != NULL && page != currentPageNumber)
+ if (currentPage != NULL)
{
fz_free_page(doc, currentPage);
currentPage = NULL;
@@ -135,11 +135,18 @@ Java_com_artifex_mupdf_MuPDFCore_gotoPageInternal(JNIEnv *env, jobject thiz, int
}
fz_catch(ctx)
{
- currentPageNumber = page;
LOGE("cannot make displaylist from page %d", pagenum);
}
- fz_free_device(dev);
- dev = NULL;
+}
+
+JNIEXPORT void JNICALL
+Java_com_artifex_mupdf_MuPDFCore_markDirtyInternal(JNIEnv *env, jobject thiz, int page)
+{
+ if (currentPage != NULL && page == pagenum)
+ {
+ fz_free_page(doc, currentPage);
+ currentPage = NULL;
+ }
}
JNIEXPORT float JNICALL
@@ -157,6 +164,12 @@ Java_com_artifex_mupdf_MuPDFCore_getPageHeight(JNIEnv *env, jobject thiz)
}
JNIEXPORT jboolean JNICALL
+Java_com_artifex_mupdf_MuPDFCore_javascriptSupported(JNIEnv *env, jobject thiz)
+{
+ return fz_javascript_supported();
+}
+
+JNIEXPORT jboolean JNICALL
Java_com_artifex_mupdf_MuPDFCore_drawPage(JNIEnv *env, jobject thiz, jobject bitmap,
int pageW, int pageH, int patchX, int patchY, int patchW, int patchH)
{
@@ -614,6 +627,59 @@ Java_com_artifex_mupdf_MuPDFCore_getPageLinksInternal(JNIEnv * env, jobject thiz
return arr;
}
+JNIEXPORT jobjectArray JNICALL
+Java_com_artifex_mupdf_MuPDFCore_getWidgetAreasInternal(JNIEnv * env, jobject thiz, int pageNumber)
+{
+ jclass rectFClass;
+ jmethodID ctor;
+ jobjectArray arr;
+ jobject rectF;
+ fz_interactive *idoc;
+ fz_widget *widget;
+ fz_matrix ctm;
+ float zoom;
+ int count;
+
+ rectFClass = (*env)->FindClass(env, "android/graphics/RectF");
+ if (rectFClass == NULL) return NULL;
+ ctor = (*env)->GetMethodID(env, rectFClass, "<init>", "(FFFF)V");
+ if (ctor == NULL) return NULL;
+
+ Java_com_artifex_mupdf_MuPDFCore_gotoPageInternal(env, thiz, pageNumber);
+ if (currentPageNumber == -1 || currentPage == NULL)
+ return NULL;
+
+ idoc = fz_interact(doc);
+ if (idoc == NULL)
+ return NULL;
+
+ zoom = resolution / 72;
+ ctm = fz_scale(zoom, zoom);
+
+ count = 0;
+ for (widget = fz_first_widget(idoc, currentPage); widget; widget = fz_next_widget(idoc, widget))
+ count ++;
+
+ arr = (*env)->NewObjectArray(env, count, rectFClass, NULL);
+ if (arr == NULL) return NULL;
+
+ count = 0;
+ for (widget = fz_first_widget(idoc, currentPage); widget; widget = fz_next_widget(idoc, widget))
+ {
+ fz_rect rect = fz_transform_rect(ctm, *fz_widget_bbox(widget));
+
+ rectF = (*env)->NewObject(env, rectFClass, ctor,
+ (float)rect.x0, (float)rect.y0, (float)rect.x1, (float)rect.y1);
+ if (rectF == NULL) return NULL;
+ (*env)->SetObjectArrayElement(env, arr, count, rectF);
+ (*env)->DeleteLocalRef(env, rectF);
+
+ count ++;
+ }
+
+ return arr;
+}
+
JNIEXPORT int JNICALL
Java_com_artifex_mupdf_MuPDFCore_getPageLink(JNIEnv * env, jobject thiz, int pageNumber, float x, float y)
{
@@ -657,3 +723,49 @@ Java_com_artifex_mupdf_MuPDFCore_getPageLink(JNIEnv * env, jobject thiz, int pag
return link->dest.ld.gotor.page;
return -1;
}
+
+JNIEXPORT int JNICALL
+Java_com_artifex_mupdf_MuPDFCore_passClickEventInternal(JNIEnv * env, jobject thiz, int pageNumber, float x, float y)
+{
+ fz_matrix ctm;
+ fz_interactive *idoc = fz_interact(doc);
+ float zoom;
+ fz_point p;
+ fz_ui_event event;
+ int changed = 0;
+
+ if (idoc == NULL)
+ return 0;
+
+ Java_com_artifex_mupdf_MuPDFCore_gotoPageInternal(env, thiz, pageNumber);
+ if (currentPageNumber == -1 || currentPage == NULL)
+ return 0;
+
+ p.x = x;
+ p.y = y;
+
+ /* Ultimately we should probably return a pointer to a java structure
+ * with the link details in, but for now, page number will suffice.
+ */
+ zoom = resolution / 72;
+ ctm = fz_scale(zoom, zoom);
+ ctm = fz_invert_matrix(ctm);
+
+ p = fz_transform_point(ctm, p);
+
+ fz_try(ctx)
+ {
+ event.etype = FZ_EVENT_TYPE_POINTER;
+ event.event.pointer.pt = p;
+ event.event.pointer.ptype = FZ_POINTER_DOWN;
+ changed = fz_pass_event(idoc, currentPage, &event);
+ event.event.pointer.ptype = FZ_POINTER_UP;
+ changed |= fz_pass_event(idoc, currentPage, &event);
+ }
+ fz_catch(ctx)
+ {
+ LOGE("passClickEvent: %s", ctx->error->message);
+ }
+
+ return changed;
+}
diff --git a/android/src/com/artifex/mupdf/MuPDFActivity.java b/android/src/com/artifex/mupdf/MuPDFActivity.java
index c530b01b..81d5e6ee 100644
--- a/android/src/com/artifex/mupdf/MuPDFActivity.java
+++ b/android/src/com/artifex/mupdf/MuPDFActivity.java
@@ -212,26 +212,30 @@ public class MuPDFActivity extends Activity
private boolean showButtonsDisabled;
public boolean onSingleTapUp(MotionEvent e) {
- if (e.getX() < super.getWidth()/TAP_PAGE_MARGIN) {
- super.moveToPrevious();
- } else if (e.getX() > super.getWidth()*(TAP_PAGE_MARGIN-1)/TAP_PAGE_MARGIN) {
- super.moveToNext();
- } else if (!showButtonsDisabled) {
- int linkPage = -1;
- if (mLinkState != LinkState.INHIBIT) {
- MuPDFPageView pageView = (MuPDFPageView) mDocView.getDisplayedView();
- if (pageView != null) {
+ if (!showButtonsDisabled) {
+ MuPDFPageView pageView = (MuPDFPageView) mDocView.getDisplayedView();
+ if (MuPDFCore.javascriptSupported() && pageView.passClickEvent(e.getX(), e.getY())) {
+ // If the page consumes the event do nothing else
+ } else if (e.getX() < super.getWidth()/TAP_PAGE_MARGIN) {
+ super.moveToPrevious();
+ } else if (e.getX() > super.getWidth()*(TAP_PAGE_MARGIN-1)/TAP_PAGE_MARGIN) {
+ super.moveToNext();
+ } else {
+ int linkPage = -1;
+ if (mLinkState != LinkState.INHIBIT) {
+ if (pageView != null) {
// XXX linkPage = pageView.hitLinkPage(e.getX(), e.getY());
+ }
}
- }
- if (linkPage != -1) {
- mDocView.setDisplayedViewIndex(linkPage);
- } else {
- if (!mButtonsVisible) {
- showButtons();
+ if (linkPage != -1) {
+ mDocView.setDisplayedViewIndex(linkPage);
} else {
- hideButtons();
+ if (!mButtonsVisible) {
+ showButtons();
+ } else {
+ hideButtons();
+ }
}
}
}
@@ -284,7 +288,7 @@ public class MuPDFActivity extends Activity
protected void onSettle(View v) {
// When the layout has settled ask the page to render
// in HQ
- ((PageView)v).addHq();
+ ((PageView)v).addHq(false);
}
protected void onUnsettle(View v) {
diff --git a/android/src/com/artifex/mupdf/MuPDFCore.java b/android/src/com/artifex/mupdf/MuPDFCore.java
index b52a3682..e7653f9e 100644
--- a/android/src/com/artifex/mupdf/MuPDFCore.java
+++ b/android/src/com/artifex/mupdf/MuPDFCore.java
@@ -20,21 +20,26 @@ public class MuPDFCore
/* The native functions */
private static native int openFile(String filename);
private static native int countPagesInternal();
+ private static native void markDirtyInternal(int page);
private static native void gotoPageInternal(int localActionPageNum);
private static native float getPageWidth();
private static native float getPageHeight();
- public static native void drawPage(Bitmap bitmap,
+ private static native void drawPage(Bitmap bitmap,
int pageW, int pageH,
int patchX, int patchY,
int patchW, int patchH);
- public static native RectF[] searchPage(String text);
- public static native int getPageLink(int page, float x, float y);
- public static native LinkInfo [] getPageLinksInternal(int page);
- public static native OutlineItem [] getOutlineInternal();
- public static native boolean hasOutlineInternal();
- public static native boolean needsPasswordInternal();
- public static native boolean authenticatePasswordInternal(String password);
- public static native void destroying();
+ private static native RectF[] searchPage(String text);
+ private static native int getPageLink(int page, float x, float y);
+ private static native int passClickEventInternal(int page, float x, float y);
+ private static native LinkInfo [] getPageLinksInternal(int page);
+ private static native RectF[] getWidgetAreasInternal(int page);
+ private static native OutlineItem [] getOutlineInternal();
+ private static native boolean hasOutlineInternal();
+ private static native boolean needsPasswordInternal();
+ private static native boolean authenticatePasswordInternal(String password);
+ private static native void destroying();
+
+ public static native boolean javascriptSupported();
public MuPDFCore(String filename) throws Exception
{
@@ -57,7 +62,7 @@ public class MuPDFCore
}
/* Shim function */
- public void gotoPage(int page)
+ private void gotoPage(int page)
{
if (page > numPages-1)
page = numPages-1;
@@ -90,6 +95,19 @@ public class MuPDFCore
return bm;
}
+ public synchronized boolean passClickEvent(int page, float x, float y) {
+ boolean changed = passClickEventInternal(page, x, y) != 0;
+
+ if (changed) {
+ if (page == pageNum)
+ pageNum = -1;
+
+ markDirtyInternal(page);
+ }
+
+ return changed;
+ }
+
public synchronized int hitLinkPage(int page, float x, float y) {
return getPageLink(page, x, y);
}
@@ -98,6 +116,10 @@ public class MuPDFCore
return getPageLinksInternal(page);
}
+ public synchronized RectF [] getWidgetAreas(int page) {
+ return getWidgetAreasInternal(page);
+ }
+
public synchronized RectF [] searchPage(int page, String text) {
gotoPage(page);
return searchPage(text);
diff --git a/android/src/com/artifex/mupdf/MuPDFPageView.java b/android/src/com/artifex/mupdf/MuPDFPageView.java
index 6294bc55..9cb430ef 100644
--- a/android/src/com/artifex/mupdf/MuPDFPageView.java
+++ b/android/src/com/artifex/mupdf/MuPDFPageView.java
@@ -3,9 +3,14 @@ package com.artifex.mupdf;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Point;
+import android.graphics.PointF;
+import android.graphics.RectF;
public class MuPDFPageView extends PageView {
private final MuPDFCore mCore;
+ private SafeAsyncTask<Void,Void,Boolean> mPassClick;
+ private RectF mWidgetAreas[];
+ private SafeAsyncTask<Void,Void,RectF[]> mLoadWidgetAreas;
public MuPDFPageView(Context c, MuPDFCore core, Point parentSize) {
super(c, parentSize);
@@ -24,6 +29,39 @@ public class MuPDFPageView extends PageView {
return mCore.hitLinkPage(mPageNumber, docRelX, docRelY);
}
+ public boolean passClickEvent(float x, float y) {
+ float scale = mSourceScale*(float)getWidth()/(float)mSize.x;
+ final float docRelX = (x - getLeft())/scale;
+ final float docRelY = (y - getTop())/scale;
+ boolean hitWidget = false;
+
+ if (mWidgetAreas != null) {
+ for (int i = 0; i < mWidgetAreas.length && !hitWidget; i++)
+ if (mWidgetAreas[i].contains(docRelX, docRelY))
+ hitWidget = true;
+ }
+
+ if (hitWidget) {
+ mPassClick = new SafeAsyncTask<Void,Void,Boolean>() {
+ @Override
+ protected Boolean doInBackground(Void... arg0) {
+ return mCore.passClickEvent(mPageNumber, docRelX, docRelY);
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ if (result) {
+ update();
+ }
+ }
+ };
+
+ mPassClick.execute();
+ }
+
+ return hitWidget;
+ }
+
@Override
protected Bitmap drawPage(int sizeX, int sizeY,
int patchX, int patchY, int patchWidth, int patchHeight) {
@@ -34,4 +72,23 @@ public class MuPDFPageView extends PageView {
protected LinkInfo[] getLinkInfo() {
return mCore.getPageLinks(mPageNumber);
}
+
+ @Override
+ public void setPage(final int page, PointF size) {
+ mLoadWidgetAreas = new SafeAsyncTask<Void,Void,RectF[]> () {
+ @Override
+ protected RectF[] doInBackground(Void... arg0) {
+ return mCore.getWidgetAreas(page);
+ }
+
+ @Override
+ protected void onPostExecute(RectF[] result) {
+ mWidgetAreas = result;
+ }
+ };
+
+ mLoadWidgetAreas.execute();
+
+ super.setPage(page, size);
+ }
}
diff --git a/android/src/com/artifex/mupdf/PageView.java b/android/src/com/artifex/mupdf/PageView.java
index 32ff7e74..072036f4 100644
--- a/android/src/com/artifex/mupdf/PageView.java
+++ b/android/src/com/artifex/mupdf/PageView.java
@@ -317,7 +317,7 @@ public abstract class PageView extends ViewGroup {
}
}
- public void addHq() {
+ public void addHq(boolean force) {
Rect viewArea = new Rect(getLeft(),getTop(),getRight(),getBottom());
// If the viewArea's size matches the unzoomed size, there is no need for an hq patch
if (viewArea.width() != mSize.x || viewArea.height() != mSize.y) {
@@ -332,7 +332,7 @@ public abstract class PageView extends ViewGroup {
patchArea.offset(-viewArea.left, -viewArea.top);
// If being asked for the same area as last time, nothing to do
- if (patchArea.equals(mPatchArea) && patchViewSize.equals(mPatchViewSize))
+ if (patchArea.equals(mPatchArea) && patchViewSize.equals(mPatchViewSize) && !force)
return;
// Stop the drawing of previous patch if still going
@@ -373,6 +373,35 @@ public abstract class PageView extends ViewGroup {
}
}
+ public void update() {
+ // Cancel pending render task
+ if (mDrawEntire != null) {
+ mDrawEntire.cancel(true);
+ mDrawEntire = null;
+ }
+
+ if (mDrawPatch != null) {
+ mDrawPatch.cancel(true);
+ mDrawPatch = null;
+ }
+
+ // Render the page in the background
+ mDrawEntire = new SafeAsyncTask<Void,Void,Bitmap>() {
+ protected Bitmap doInBackground(Void... v) {
+ return drawPage(mSize.x, mSize.y, 0, 0, mSize.x, mSize.y);
+ }
+
+ protected void onPostExecute(Bitmap bm) {
+ mEntire.setImageBitmap(bm);
+ invalidate();
+ }
+ };
+
+ mDrawEntire.safeExecute();
+
+ addHq(true);
+ }
+
public void removeHq() {
// Stop the drawing of the patch if still going
if (mDrawPatch != null) {