summaryrefslogtreecommitdiff
path: root/android/jni/mupdf.c
diff options
context:
space:
mode:
Diffstat (limited to 'android/jni/mupdf.c')
-rw-r--r--android/jni/mupdf.c239
1 files changed, 239 insertions, 0 deletions
diff --git a/android/jni/mupdf.c b/android/jni/mupdf.c
new file mode 100644
index 00000000..ea11be2d
--- /dev/null
+++ b/android/jni/mupdf.c
@@ -0,0 +1,239 @@
+#include <jni.h>
+#include <time.h>
+#include <android/log.h>
+#include <android/bitmap.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "fitz.h"
+#include "mupdf.h"
+
+#define LOG_TAG "libmupdf"
+#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
+#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
+
+/* Set to 1 to enable debug log traces. */
+#define DEBUG 0
+
+/* Globals */
+fz_colorspace *colorspace;
+fz_glyphcache *glyphcache;
+pdf_xref *xref;
+int pagenum = 1;
+int resolution = 160;
+pdf_page *currentPage;
+float pageWidth = 100;
+float pageHeight = 100;
+
+JNIEXPORT int JNICALL Java_com_artifex_mupdf_PixmapView_mupdfOpenFile(JNIEnv * env, jobject thiz, jstring jfilename)
+{
+ const char *filename;
+ char *password = "";
+ int accelerate = 1;
+ fz_error error;
+
+ filename = (*env)->GetStringUTFChars(env, jfilename, NULL);
+ if (filename == NULL)
+ {
+ LOGE("Failed to get filename");
+ return 0;
+ }
+
+ if (accelerate)
+ fz_accelerate();
+ glyphcache = fz_newglyphcache();
+ colorspace = fz_devicergb;
+
+ LOGE("Opening document...");
+ error = pdf_openxref(&xref, filename, password);
+ if (error)
+ {
+ LOGE("Cannot open document: '%s'\n", filename);
+ return 0;
+ }
+
+ LOGE("Loading page tree...");
+ error = pdf_loadpagetree(xref);
+ if (error)
+ {
+ LOGE("Cannot load page tree: '%s'\n", filename);
+ return 0;
+ }
+ LOGE("Done! %d pages", pdf_getpagecount(xref));
+
+ return pdf_getpagecount(xref);
+}
+
+JNIEXPORT void JNICALL Java_com_artifex_mupdf_PixmapView_mupdfGotoPage(
+ JNIEnv *env,
+ jobject thiz,
+ int page)
+{
+ float zoom;
+ fz_matrix ctm;
+ fz_obj *pageobj;
+ fz_bbox bbox;
+ fz_error error;
+
+ /* In the event of an error, ensure we give a non-empty page */
+ pageWidth = 100;
+ pageHeight = 100;
+
+ /* Free any current page */
+ if (currentPage != NULL)
+ {
+ pdf_freepage(currentPage);
+ currentPage = NULL;
+ }
+
+ LOGE("Goto page %d...", page);
+ pagenum = page;
+ pageobj = pdf_getpageobject(xref, pagenum);
+ if (pageobj == NULL)
+ return;
+ error = pdf_loadpage(&currentPage, xref, pageobj);
+ if (error)
+ return;
+ zoom = resolution / 72;
+ ctm = fz_translate(0, -currentPage->mediabox.y1);
+ ctm = fz_concat(ctm, fz_scale(zoom, -zoom));
+ ctm = fz_concat(ctm, fz_rotate(currentPage->rotate));
+ bbox = fz_roundrect(fz_transformrect(ctm, currentPage->mediabox));
+ pageWidth = bbox.x1-bbox.x0;
+ pageHeight = bbox.y1-bbox.y0;
+ LOGE("Success [w=%g, h=%g]", pageWidth, pageHeight);
+}
+
+JNIEXPORT float JNICALL Java_com_artifex_mupdf_PixmapView_mupdfPageWidth(
+ JNIEnv *env,
+ jobject thiz)
+{
+ LOGE("PageWidth=%g", pageWidth);
+ return pageWidth;
+}
+
+JNIEXPORT float JNICALL Java_com_artifex_mupdf_PixmapView_mupdfPageHeight(
+ JNIEnv *env,
+ jobject thiz)
+{
+ LOGE("PageHeight=%g", pageHeight);
+ return pageHeight;
+}
+
+
+JNIEXPORT jboolean JNICALL Java_com_artifex_mupdf_PixmapView_mupdfDrawPage(
+ JNIEnv *env,
+ jobject thiz,
+ jobject bitmap,
+ int pageW,
+ int pageH,
+ int patchX,
+ int patchY,
+ int patchW,
+ int patchH)
+{
+ AndroidBitmapInfo info;
+ void* pixels;
+ int ret, i, c;
+
+ LOGI("In native method\n");
+ if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {
+ LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
+ return 0;
+ }
+
+ LOGI("Checking format\n");
+ if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
+ LOGE("Bitmap format is not RGBA_8888 !");
+ return 0;
+ }
+
+ LOGI("locking pixels\n");
+ if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {
+ LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
+ return 0;
+ }
+
+ LOGI("render page\n");
+ /* Call mupdf to render page */
+ {
+ fz_error error;
+ fz_displaylist *list;
+ fz_device *dev;
+
+ /* Render to list */
+ LOGI("make list\n");
+ list = fz_newdisplaylist();
+ LOGI("make device\n");
+ dev = fz_newlistdevice(list);
+ LOGI("render to device\n");
+ error = pdf_runpage(xref, currentPage, dev, fz_identity);
+ if (error)
+ {
+ LOGE("cannot draw page %d", pagenum);
+ return 0;
+ }
+ LOGI("free device\n");
+ fz_freedevice(dev);
+
+ /* Render to screen */
+ LOGE("Rendering page=%dx%d patch=[%d,%d,%d,%d]",
+ pageW, pageH, patchX, patchY, patchW, patchH);
+ {
+ float zoom;
+ fz_matrix ctm;
+ fz_bbox bbox;
+ fz_pixmap *pix;
+ float xscale, yscale;
+
+ zoom = resolution / 72;
+ ctm = fz_translate(0, -currentPage->mediabox.y1);
+ ctm = fz_concat(ctm, fz_scale(zoom, -zoom));
+ ctm = fz_concat(ctm, fz_rotate(currentPage->rotate));
+ bbox = fz_roundrect(fz_transformrect(ctm,currentPage->mediabox));
+
+ LOGE("mediabox=%g %g %g %g zoom=%g rotate=%d",
+ currentPage->mediabox.x0,
+ currentPage->mediabox.y0,
+ currentPage->mediabox.x1,
+ currentPage->mediabox.y1,
+ zoom,
+ currentPage->rotate);
+ LOGE("ctm = [%g %g %g %g %g %g] to [%d %d %d %d]", ctm.a, ctm.b, ctm.c, ctm.d, ctm.e, ctm.f, bbox.x0, bbox.y0, bbox.x1, bbox.y1);
+ /* Now, adjust ctm so that it would give the correct page width
+ * heights. */
+ xscale = (float)pageW/(float)(bbox.x1-bbox.x0);
+ yscale = (float)pageH/(float)(bbox.y1-bbox.y0);
+ ctm = fz_concat(ctm, fz_scale(xscale, yscale));
+ bbox = fz_roundrect(fz_transformrect(ctm,currentPage->mediabox));
+ LOGE("ctm = [%g %g %g %g %g %g] to [%d %d %d %d]", ctm.a, ctm.b, ctm.c, ctm.d, ctm.e, ctm.f, bbox.x0, bbox.y0, bbox.x1, bbox.y1);
+
+ pix = fz_newpixmapwithdata(colorspace,
+ patchX,
+ patchY,
+ patchW,
+ patchH,
+ pixels);
+ LOGE("Clearing");
+ fz_clearpixmapwithcolor(pix, 0xff);
+ LOGE("Cleared");
+ dev = fz_newdrawdevice(glyphcache, pix);
+ fz_executedisplaylist(list, dev, ctm);
+ fz_freedevice(dev);
+ fz_droppixmap(pix);
+ }
+ LOGE("Rendered");
+ fz_freedisplaylist(list);
+ }
+
+ AndroidBitmap_unlockPixels(env, bitmap);
+
+ return 1;
+}
+
+void android_log(char *err, int n)
+{
+ LOGE(err, n);
+}