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.c2389
1 files changed, 0 insertions, 2389 deletions
diff --git a/android/jni/mupdf.c b/android/jni/mupdf.c
deleted file mode 100644
index bb827778..00000000
--- a/android/jni/mupdf.c
+++ /dev/null
@@ -1,2389 +0,0 @@
-#include <jni.h>
-#include <time.h>
-#include <pthread.h>
-#include <android/log.h>
-#include <android/bitmap.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-#ifdef NDK_PROFILER
-#include "prof.h"
-#endif
-
-#include "mupdf/fitz.h"
-#include "mupdf/pdf.h"
-
-#define JNI_FN(A) Java_com_artifex_mupdfdemo_ ## A
-#define PACKAGENAME "com/artifex/mupdfdemo"
-
-#define LOG_TAG "libmupdf"
-#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
-#define LOGT(...) __android_log_print(ANDROID_LOG_INFO,"alert",__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
-
-/* Enable to log rendering times (render each frame 100 times and time) */
-#undef TIME_DISPLAY_LIST
-
-#define MAX_SEARCH_HITS (500)
-#define NUM_CACHE (3)
-#define STRIKE_HEIGHT (0.375f)
-#define UNDERLINE_HEIGHT (0.075f)
-#define LINE_THICKNESS (0.07f)
-#define INK_THICKNESS (4.0f)
-#define SMALL_FLOAT (0.00001)
-
-enum
-{
- NONE,
- TEXT,
- LISTBOX,
- COMBOBOX
-};
-
-typedef struct rect_node_s rect_node;
-
-struct rect_node_s
-{
- fz_rect rect;
- rect_node *next;
-};
-
-typedef struct
-{
- int number;
- int width;
- int height;
- fz_rect media_box;
- fz_page *page;
- rect_node *changed_rects;
- rect_node *hq_changed_rects;
- fz_display_list *page_list;
- fz_display_list *annot_list;
-} page_cache;
-
-typedef struct globals_s globals;
-
-struct globals_s
-{
- fz_colorspace *colorspace;
- fz_document *doc;
- int resolution;
- fz_context *ctx;
- fz_rect *hit_bbox;
- int current;
- char *current_path;
-
- page_cache pages[NUM_CACHE];
-
- int alerts_initialised;
- // fin_lock and fin_lock2 are used during shutdown. The two waiting tasks
- // show_alert and waitForAlertInternal respectively take these locks while
- // waiting. During shutdown, the conditions are signaled and then the fin_locks
- // are taken momentarily to ensure the blocked threads leave the controlled
- // area of code before the mutexes and condition variables are destroyed.
- pthread_mutex_t fin_lock;
- pthread_mutex_t fin_lock2;
- // alert_lock is the main lock guarding the variables directly below.
- pthread_mutex_t alert_lock;
- // Flag indicating if the alert system is active. When not active, both
- // show_alert and waitForAlertInternal return immediately.
- int alerts_active;
- // Pointer to the alert struct passed in by show_alert, and valid while
- // show_alert is blocked.
- pdf_alert_event *current_alert;
- // Flag and condition varibles to signal a request is present and a reply
- // is present, respectively. The condition variables alone are not sufficient
- // because of the pthreads permit spurious signals.
- int alert_request;
- int alert_reply;
- pthread_cond_t alert_request_cond;
- pthread_cond_t alert_reply_cond;
-
- // For the buffer reading mode, we need to implement stream reading, which
- // needs access to the following.
- JNIEnv *env;
- jclass thiz;
-};
-
-static jfieldID global_fid;
-static jfieldID buffer_fid;
-
-static void drop_changed_rects(fz_context *ctx, rect_node **nodePtr)
-{
- rect_node *node = *nodePtr;
- while (node)
- {
- rect_node *tnode = node;
- node = node->next;
- fz_free(ctx, tnode);
- }
-
- *nodePtr = NULL;
-}
-
-static void drop_page_cache(globals *glo, page_cache *pc)
-{
- fz_context *ctx = glo->ctx;
- fz_document *doc = glo->doc;
-
- LOGI("Drop page %d", pc->number);
- fz_drop_display_list(ctx, pc->page_list);
- pc->page_list = NULL;
- fz_drop_display_list(ctx, pc->annot_list);
- pc->annot_list = NULL;
- fz_free_page(doc, pc->page);
- pc->page = NULL;
- drop_changed_rects(ctx, &pc->changed_rects);
- drop_changed_rects(ctx, &pc->hq_changed_rects);
-}
-
-static void dump_annotation_display_lists(globals *glo)
-{
- fz_context *ctx = glo->ctx;
- int i;
-
- for (i = 0; i < NUM_CACHE; i++) {
- fz_drop_display_list(ctx, glo->pages[i].annot_list);
- glo->pages[i].annot_list = NULL;
- }
-}
-
-static void show_alert(globals *glo, pdf_alert_event *alert)
-{
- pthread_mutex_lock(&glo->fin_lock2);
- pthread_mutex_lock(&glo->alert_lock);
-
- LOGT("Enter show_alert: %s", alert->title);
- alert->button_pressed = 0;
-
- if (glo->alerts_active)
- {
- glo->current_alert = alert;
- glo->alert_request = 1;
- pthread_cond_signal(&glo->alert_request_cond);
-
- while (glo->alerts_active && !glo->alert_reply)
- pthread_cond_wait(&glo->alert_reply_cond, &glo->alert_lock);
- glo->alert_reply = 0;
- glo->current_alert = NULL;
- }
-
- LOGT("Exit show_alert");
-
- pthread_mutex_unlock(&glo->alert_lock);
- pthread_mutex_unlock(&glo->fin_lock2);
-}
-
-static void event_cb(pdf_doc_event *event, void *data)
-{
- globals *glo = (globals *)data;
-
- switch (event->type)
- {
- case PDF_DOCUMENT_EVENT_ALERT:
- show_alert(glo, pdf_access_alert_event(event));
- break;
- }
-}
-
-static void alerts_init(globals *glo)
-{
- pdf_document *idoc = pdf_specifics(glo->doc);
-
- if (!idoc || glo->alerts_initialised)
- return;
-
- glo->alerts_active = 0;
- glo->alert_request = 0;
- glo->alert_reply = 0;
- pthread_mutex_init(&glo->fin_lock, NULL);
- pthread_mutex_init(&glo->fin_lock2, NULL);
- pthread_mutex_init(&glo->alert_lock, NULL);
- pthread_cond_init(&glo->alert_request_cond, NULL);
- pthread_cond_init(&glo->alert_reply_cond, NULL);
-
- pdf_set_doc_event_callback(idoc, event_cb, glo);
- LOGT("alert_init");
- glo->alerts_initialised = 1;
-}
-
-static void alerts_fin(globals *glo)
-{
- pdf_document *idoc = pdf_specifics(glo->doc);
- if (!glo->alerts_initialised)
- return;
-
- LOGT("Enter alerts_fin");
- if (idoc)
- pdf_set_doc_event_callback(idoc, NULL, NULL);
-
- // Set alerts_active false and wake up show_alert and waitForAlertInternal,
- pthread_mutex_lock(&glo->alert_lock);
- glo->current_alert = NULL;
- glo->alerts_active = 0;
- pthread_cond_signal(&glo->alert_request_cond);
- pthread_cond_signal(&glo->alert_reply_cond);
- pthread_mutex_unlock(&glo->alert_lock);
-
- // Wait for the fin_locks.
- pthread_mutex_lock(&glo->fin_lock);
- pthread_mutex_unlock(&glo->fin_lock);
- pthread_mutex_lock(&glo->fin_lock2);
- pthread_mutex_unlock(&glo->fin_lock2);
-
- pthread_cond_destroy(&glo->alert_reply_cond);
- pthread_cond_destroy(&glo->alert_request_cond);
- pthread_mutex_destroy(&glo->alert_lock);
- pthread_mutex_destroy(&glo->fin_lock2);
- pthread_mutex_destroy(&glo->fin_lock);
- LOGT("Exit alerts_fin");
- glo->alerts_initialised = 0;
-}
-
-static globals *get_globals(JNIEnv *env, jobject thiz)
-{
- globals *glo = (globals *)(void *)((*env)->GetLongField(env, thiz, global_fid));
- if (glo != NULL)
- {
- glo->env = env;
- glo->thiz = thiz;
- }
- return glo;
-}
-
-JNIEXPORT jlong JNICALL
-JNI_FN(MuPDFCore_openFile)(JNIEnv * env, jobject thiz, jstring jfilename)
-{
- const char *filename;
- globals *glo;
- fz_context *ctx;
- jclass clazz;
-
-#ifdef NDK_PROFILER
- monstartup("libmupdf.so");
-#endif
-
- clazz = (*env)->GetObjectClass(env, thiz);
- global_fid = (*env)->GetFieldID(env, clazz, "globals", "J");
-
- glo = calloc(1, sizeof(*glo));
- if (glo == NULL)
- return 0;
- glo->resolution = 160;
- glo->alerts_initialised = 0;
-
- filename = (*env)->GetStringUTFChars(env, jfilename, NULL);
- if (filename == NULL)
- {
- LOGE("Failed to get filename");
- free(glo);
- return 0;
- }
-
- /* 128 MB store for low memory devices. Tweak as necessary. */
- glo->ctx = ctx = fz_new_context(NULL, NULL, 128 << 20);
- if (!ctx)
- {
- LOGE("Failed to initialise context");
- (*env)->ReleaseStringUTFChars(env, jfilename, filename);
- free(glo);
- return 0;
- }
-
- glo->doc = NULL;
- fz_try(ctx)
- {
- glo->colorspace = fz_device_rgb(ctx);
-
- LOGE("Opening document...");
- fz_try(ctx)
- {
- glo->current_path = fz_strdup(ctx, (char *)filename);
- glo->doc = fz_open_document(ctx, (char *)filename);
- alerts_init(glo);
- }
- fz_catch(ctx)
- {
- fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot open document: '%s'", filename);
- }
- LOGE("Done!");
- }
- fz_catch(ctx)
- {
- LOGE("Failed: %s", ctx->error->message);
- fz_close_document(glo->doc);
- glo->doc = NULL;
- fz_free_context(ctx);
- glo->ctx = NULL;
- free(glo);
- glo = NULL;
- }
-
- (*env)->ReleaseStringUTFChars(env, jfilename, filename);
-
- return (jlong)(void *)glo;
-}
-
-static int bufferStreamRead(fz_stream *stream, unsigned char *buf, int len)
-{
- globals *glo = (globals *)stream->state;
- JNIEnv *env = glo->env;
- jbyteArray array = (jbyteArray)(void *)((*env)->GetObjectField(env, glo->thiz, buffer_fid));
- int arrayLength = (*env)->GetArrayLength(env, array);
-
- if (stream->pos > arrayLength)
- stream->pos = arrayLength;
- if (stream->pos < 0)
- stream->pos = 0;
- if (len + stream->pos > arrayLength)
- len = arrayLength - stream->pos;
-
- (*env)->GetByteArrayRegion(env, array, stream->pos, len, buf);
- (*env)->DeleteLocalRef(env, array);
- return len;
-}
-
-static void bufferStreamClose(fz_context *ctx, void *state)
-{
- /* Nothing to do */
-}
-
-static void bufferStreamSeek(fz_stream *stream, int offset, int whence)
-{
- globals *glo = (globals *)stream->state;
- JNIEnv *env = glo->env;
- jbyteArray array = (jbyteArray)(void *)((*env)->GetObjectField(env, glo->thiz, buffer_fid));
- int arrayLength = (*env)->GetArrayLength(env, array);
-
- (*env)->DeleteLocalRef(env, array);
-
- if (whence == 0) /* SEEK_SET */
- stream->pos = offset;
- else if (whence == 1) /* SEEK_CUR */
- stream->pos += offset;
- else if (whence == 2) /* SEEK_END */
- stream->pos = arrayLength + offset;
-
- if (stream->pos > arrayLength)
- stream->pos = arrayLength;
- if (stream->pos < 0)
- stream->pos = 0;
-
- stream->rp = stream->bp;
- stream->wp = stream->bp;
-}
-
-JNIEXPORT jlong JNICALL
-JNI_FN(MuPDFCore_openBuffer)(JNIEnv * env, jobject thiz)
-{
- globals *glo;
- fz_context *ctx;
- jclass clazz;
- fz_stream *stream;
-
-#ifdef NDK_PROFILER
- monstartup("libmupdf.so");
-#endif
-
- clazz = (*env)->GetObjectClass(env, thiz);
- global_fid = (*env)->GetFieldID(env, clazz, "globals", "J");
-
- glo = calloc(1, sizeof(*glo));
- if (glo == NULL)
- return 0;
- glo->resolution = 160;
- glo->alerts_initialised = 0;
- glo->env = env;
- glo->thiz = thiz;
- buffer_fid = (*env)->GetFieldID(env, clazz, "fileBuffer", "[B");
-
- /* 128 MB store for low memory devices. Tweak as necessary. */
- glo->ctx = ctx = fz_new_context(NULL, NULL, 128 << 20);
- if (!ctx)
- {
- LOGE("Failed to initialise context");
- free(glo);
- return 0;
- }
-
- glo->doc = NULL;
- fz_try(ctx)
- {
- stream = fz_new_stream(ctx, glo, bufferStreamRead, bufferStreamClose);
- stream->seek = bufferStreamSeek;
-
- glo->colorspace = fz_device_rgb(ctx);
-
- LOGE("Opening document...");
- fz_try(ctx)
- {
- glo->current_path = NULL;
- glo->doc = fz_open_document_with_stream(ctx, "", stream);
- alerts_init(glo);
- }
- fz_catch(ctx)
- {
- fz_throw(ctx, FZ_ERROR_GENERIC, "Cannot open memory document");
- }
- LOGE("Done!");
- }
- fz_always(ctx)
- {
- fz_close(stream);
- }
- fz_catch(ctx)
- {
- LOGE("Failed: %s", ctx->error->message);
- fz_close_document(glo->doc);
- glo->doc = NULL;
- fz_free_context(ctx);
- glo->ctx = NULL;
- free(glo);
- glo = NULL;
- }
-
- return (jlong)(void *)glo;
-}
-
-JNIEXPORT int JNICALL
-JNI_FN(MuPDFCore_countPagesInternal)(JNIEnv *env, jobject thiz)
-{
- globals *glo = get_globals(env, thiz);
- fz_context *ctx = glo->ctx;
- int count = 0;
-
- fz_try(ctx)
- {
- count = fz_count_pages(glo->doc);
- }
- fz_catch(ctx)
- {
- LOGE("exception while counting pages: %s", ctx->error->message);
- }
- return count;
-}
-
-JNIEXPORT jstring JNICALL
-JNI_FN(MuPDFCore_fileFormatInternal)(JNIEnv * env, jobject thiz)
-{
- char info[64];
- globals *glo = get_globals(env, thiz);
-
- fz_meta(glo->doc, FZ_META_FORMAT_INFO, info, sizeof(info));
-
- return (*env)->NewStringUTF(env, info);
-}
-
-JNIEXPORT void JNICALL
-JNI_FN(MuPDFCore_gotoPageInternal)(JNIEnv *env, jobject thiz, int page)
-{
- int i;
- int furthest;
- int furthest_dist = -1;
- float zoom;
- fz_matrix ctm;
- fz_irect bbox;
- page_cache *pc;
- globals *glo = get_globals(env, thiz);
- fz_context *ctx = glo->ctx;
-
- for (i = 0; i < NUM_CACHE; i++)
- {
- if (glo->pages[i].page != NULL && glo->pages[i].number == page)
- {
- /* The page is already cached */
- glo->current = i;
- return;
- }
-
- if (glo->pages[i].page == NULL)
- {
- /* cache record unused, and so a good one to use */
- furthest = i;
- furthest_dist = INT_MAX;
- }
- else
- {
- int dist = abs(glo->pages[i].number - page);
-
- /* Further away - less likely to be needed again */
- if (dist > furthest_dist)
- {
- furthest_dist = dist;
- furthest = i;
- }
- }
- }
-
- glo->current = furthest;
- pc = &glo->pages[glo->current];
-
- drop_page_cache(glo, pc);
-
- /* In the event of an error, ensure we give a non-empty page */
- pc->width = 100;
- pc->height = 100;
-
- pc->number = page;
- LOGE("Goto page %d...", page);
- fz_try(ctx)
- {
- fz_rect rect;
- LOGI("Load page %d", pc->number);
- pc->page = fz_load_page(glo->doc, pc->number);
- zoom = glo->resolution / 72;
- fz_bound_page(glo->doc, pc->page, &pc->media_box);
- fz_scale(&ctm, zoom, zoom);
- rect = pc->media_box;
- fz_round_rect(&bbox, fz_transform_rect(&rect, &ctm));
- pc->width = bbox.x1-bbox.x0;
- pc->height = bbox.y1-bbox.y0;
- }
- fz_catch(ctx)
- {
- LOGE("cannot make displaylist from page %d", pc->number);
- }
-}
-
-JNIEXPORT float JNICALL
-JNI_FN(MuPDFCore_getPageWidth)(JNIEnv *env, jobject thiz)
-{
- globals *glo = get_globals(env, thiz);
- LOGE("PageWidth=%d", glo->pages[glo->current].width);
- return glo->pages[glo->current].width;
-}
-
-JNIEXPORT float JNICALL
-JNI_FN(MuPDFCore_getPageHeight)(JNIEnv *env, jobject thiz)
-{
- globals *glo = get_globals(env, thiz);
- LOGE("PageHeight=%d", glo->pages[glo->current].height);
- return glo->pages[glo->current].height;
-}
-
-JNIEXPORT jboolean JNICALL
-JNI_FN(MuPDFCore_javascriptSupported)(JNIEnv *env, jobject thiz)
-{
- return fz_javascript_supported();
-}
-
-static void update_changed_rects(globals *glo, page_cache *pc, pdf_document *idoc)
-{
- fz_annot *annot;
-
- pdf_update_page(idoc, (pdf_page *)pc->page);
- while ((annot = (fz_annot *)pdf_poll_changed_annot(idoc, (pdf_page *)pc->page)) != NULL)
- {
- /* FIXME: We bound the annot twice here */
- rect_node *node = fz_malloc_struct(glo->ctx, rect_node);
- fz_bound_annot(glo->doc, annot, &node->rect);
- node->next = pc->changed_rects;
- pc->changed_rects = node;
-
- node = fz_malloc_struct(glo->ctx, rect_node);
- fz_bound_annot(glo->doc, annot, &node->rect);
- node->next = pc->hq_changed_rects;
- pc->hq_changed_rects = node;
- }
-}
-
-JNIEXPORT jboolean JNICALL
-JNI_FN(MuPDFCore_drawPage)(JNIEnv *env, jobject thiz, jobject bitmap,
- int pageW, int pageH, int patchX, int patchY, int patchW, int patchH)
-{
- AndroidBitmapInfo info;
- void *pixels;
- int ret;
- fz_device *dev = NULL;
- float zoom;
- fz_matrix ctm;
- fz_irect bbox;
- fz_rect rect;
- fz_pixmap *pix = NULL;
- float xscale, yscale;
- globals *glo = get_globals(env, thiz);
- fz_context *ctx = glo->ctx;
- fz_document *doc = glo->doc;
- page_cache *pc = &glo->pages[glo->current];
- int hq = (patchW < pageW || patchH < pageH);
- fz_matrix scale;
-
- if (pc->page == NULL)
- return 0;
-
- fz_var(pix);
- fz_var(dev);
-
- 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;
- }
-
- /* Call mupdf to render display list to screen */
- LOGE("Rendering page(%d)=%dx%d patch=[%d,%d,%d,%d]",
- pc->number, pageW, pageH, patchX, patchY, patchW, patchH);
-
- fz_try(ctx)
- {
- pdf_document *idoc = pdf_specifics(doc);
-
- if (idoc)
- {
- /* Update the changed-rects for both hq patch and main bitmap */
- update_changed_rects(glo, pc, idoc);
-
- /* Then drop the changed-rects for the bitmap we're about to
- render because we are rendering the entire area */
- drop_changed_rects(ctx, hq ? &pc->hq_changed_rects : &pc->changed_rects);
- }
-
- if (pc->page_list == NULL)
- {
- /* Render to list */
- pc->page_list = fz_new_display_list(ctx);
- dev = fz_new_list_device(ctx, pc->page_list);
- fz_run_page_contents(doc, pc->page, dev, &fz_identity, NULL);
- fz_free_device(dev);
- dev = NULL;
- }
- if (pc->annot_list == NULL)
- {
- fz_annot *annot;
- pc->annot_list = fz_new_display_list(ctx);
- dev = fz_new_list_device(ctx, pc->annot_list);
- for (annot = fz_first_annot(doc, pc->page); annot; annot = fz_next_annot(doc, annot))
- fz_run_annot(doc, pc->page, annot, dev, &fz_identity, NULL);
- fz_free_device(dev);
- dev = NULL;
- }
- bbox.x0 = patchX;
- bbox.y0 = patchY;
- bbox.x1 = patchX + patchW;
- bbox.y1 = patchY + patchH;
- pix = fz_new_pixmap_with_bbox_and_data(ctx, glo->colorspace, &bbox, pixels);
- if (pc->page_list == NULL && pc->annot_list == NULL)
- {
- fz_clear_pixmap_with_value(ctx, pix, 0xd0);
- break;
- }
- fz_clear_pixmap_with_value(ctx, pix, 0xff);
-
- zoom = glo->resolution / 72;
- fz_scale(&ctm, zoom, zoom);
- rect = pc->media_box;
- fz_round_rect(&bbox, fz_transform_rect(&rect, &ctm));
- /* 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);
- fz_concat(&ctm, &ctm, fz_scale(&scale, xscale, yscale));
- rect = pc->media_box;
- fz_transform_rect(&rect, &ctm);
- dev = fz_new_draw_device(ctx, pix);
-#ifdef TIME_DISPLAY_LIST
- {
- clock_t time;
- int i;
-
- LOGE("Executing display list");
- time = clock();
- for (i=0; i<100;i++) {
-#endif
- if (pc->page_list)
- fz_run_display_list(pc->page_list, dev, &ctm, &rect, NULL);
- if (pc->annot_list)
- fz_run_display_list(pc->annot_list, dev, &ctm, &rect, NULL);
-#ifdef TIME_DISPLAY_LIST
- }
- time = clock() - time;
- LOGE("100 renders in %d (%d per sec)", time, CLOCKS_PER_SEC);
- }
-#endif
- fz_free_device(dev);
- dev = NULL;
- fz_drop_pixmap(ctx, pix);
- LOGE("Rendered");
- }
- fz_always(ctx)
- {
- fz_free_device(dev);
- dev = NULL;
- }
- fz_catch(ctx)
- {
- LOGE("Render failed");
- }
-
- AndroidBitmap_unlockPixels(env, bitmap);
-
- return 1;
-}
-
-static char *widget_type_string(int t)
-{
- switch(t)
- {
- case PDF_WIDGET_TYPE_PUSHBUTTON: return "pushbutton";
- case PDF_WIDGET_TYPE_CHECKBOX: return "checkbox";
- case PDF_WIDGET_TYPE_RADIOBUTTON: return "radiobutton";
- case PDF_WIDGET_TYPE_TEXT: return "text";
- case PDF_WIDGET_TYPE_LISTBOX: return "listbox";
- case PDF_WIDGET_TYPE_COMBOBOX: return "combobox";
- default: return "non-widget";
- }
-}
-JNIEXPORT jboolean JNICALL
-JNI_FN(MuPDFCore_updatePageInternal)(JNIEnv *env, jobject thiz, jobject bitmap, int page,
- int pageW, int pageH, int patchX, int patchY, int patchW, int patchH)
-{
- AndroidBitmapInfo info;
- void *pixels;
- int ret;
- fz_device *dev = NULL;
- float zoom;
- fz_matrix ctm;
- fz_irect bbox;
- fz_rect rect;
- fz_pixmap *pix = NULL;
- float xscale, yscale;
- pdf_document *idoc;
- page_cache *pc = NULL;
- int hq = (patchW < pageW || patchH < pageH);
- int i;
- globals *glo = get_globals(env, thiz);
- fz_context *ctx = glo->ctx;
- fz_document *doc = glo->doc;
- rect_node *crect;
- fz_matrix scale;
-
- for (i = 0; i < NUM_CACHE; i++)
- {
- if (glo->pages[i].page != NULL && glo->pages[i].number == page)
- {
- pc = &glo->pages[i];
- break;
- }
- }
-
- if (pc == NULL)
- {
- /* Without a cached page object we cannot perform a partial update so
- render the entire bitmap instead */
- JNI_FN(MuPDFCore_gotoPageInternal)(env, thiz, page);
- return JNI_FN(MuPDFCore_drawPage)(env, thiz, bitmap, pageW, pageH, patchX, patchY, patchW, patchH);
- }
-
- idoc = pdf_specifics(doc);
-
- fz_var(pix);
- fz_var(dev);
-
- 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;
- }
-
- /* Call mupdf to render display list to screen */
- LOGE("Rendering page(%d)=%dx%d patch=[%d,%d,%d,%d]",
- pc->number, pageW, pageH, patchX, patchY, patchW, patchH);
-
- fz_try(ctx)
- {
- fz_annot *annot;
-
- if (idoc)
- {
- /* Update the changed-rects for both hq patch and main bitmap */
- update_changed_rects(glo, pc, idoc);
- }
-
- if (pc->page_list == NULL)
- {
- /* Render to list */
- pc->page_list = fz_new_display_list(ctx);
- dev = fz_new_list_device(ctx, pc->page_list);
- fz_run_page_contents(doc, pc->page, dev, &fz_identity, NULL);
- fz_free_device(dev);
- dev = NULL;
- }
-
- if (pc->annot_list == NULL) {
- pc->annot_list = fz_new_display_list(ctx);
- dev = fz_new_list_device(ctx, pc->annot_list);
- for (annot = fz_first_annot(doc, pc->page); annot; annot = fz_next_annot(doc, annot))
- fz_run_annot(doc, pc->page, annot, dev, &fz_identity, NULL);
- fz_free_device(dev);
- dev = NULL;
- }
-
- bbox.x0 = patchX;
- bbox.y0 = patchY;
- bbox.x1 = patchX + patchW;
- bbox.y1 = patchY + patchH;
- pix = fz_new_pixmap_with_bbox_and_data(ctx, glo->colorspace, &bbox, pixels);
-
- zoom = glo->resolution / 72;
- fz_scale(&ctm, zoom, zoom);
- rect = pc->media_box;
- fz_round_rect(&bbox, fz_transform_rect(&rect, &ctm));
- /* 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);
- fz_concat(&ctm, &ctm, fz_scale(&scale, xscale, yscale));
- rect = pc->media_box;
- fz_transform_rect(&rect, &ctm);
-
- LOGI("Start partial update");
- for (crect = hq ? pc->hq_changed_rects : pc->changed_rects; crect; crect = crect->next)
- {
- fz_irect abox;
- fz_rect arect = crect->rect;
- fz_intersect_rect(fz_transform_rect(&arect, &ctm), &rect);
- fz_round_rect(&abox, &arect);
-
- LOGI("Update rectangle (%d, %d, %d, %d)", abox.x0, abox.y0, abox.x1, abox.y1);
- if (!fz_is_empty_irect(&abox))
- {
- LOGI("And it isn't empty");
- fz_clear_pixmap_rect_with_value(ctx, pix, 0xff, &abox);
- dev = fz_new_draw_device_with_bbox(ctx, pix, &abox);
- if (pc->page_list)
- fz_run_display_list(pc->page_list, dev, &ctm, &arect, NULL);
- if (pc->annot_list)
- fz_run_display_list(pc->annot_list, dev, &ctm, &arect, NULL);
- fz_free_device(dev);
- dev = NULL;
- }
- }
- LOGI("End partial update");
-
- /* Drop the changed rects we've just rendered */
- drop_changed_rects(ctx, hq ? &pc->hq_changed_rects : &pc->changed_rects);
-
- LOGE("Rendered");
- }
- fz_always(ctx)
- {
- fz_free_device(dev);
- dev = NULL;
- }
- fz_catch(ctx)
- {
- LOGE("Render failed");
- }
-
- fz_drop_pixmap(ctx, pix);
- AndroidBitmap_unlockPixels(env, bitmap);
-
- return 1;
-}
-
-static int
-charat(fz_text_page *page, int idx)
-{
- fz_char_and_box cab;
- return fz_text_char_at(&cab, page, idx)->c;
-}
-
-static fz_rect
-bboxcharat(fz_text_page *page, int idx)
-{
- fz_char_and_box cab;
- return fz_text_char_at(&cab, page, idx)->bbox;
-}
-
-static int
-textlen(fz_text_page *page)
-{
- int len = 0;
- int block_num;
-
- for (block_num = 0; block_num < page->len; block_num++)
- {
- fz_text_block *block;
- fz_text_line *line;
-
- if (page->blocks[block_num].type != FZ_PAGE_BLOCK_TEXT)
- continue;
- block = page->blocks[block_num].u.text;
- for (line = block->lines; line < block->lines + block->len; line++)
- {
- fz_text_span *span;
-
- for (span = line->first_span; span; span = span->next)
- {
- len += span->len;
- }
- len++; /* pseudo-newline */
- }
- }
- return len;
-}
-
-static int
-countOutlineItems(fz_outline *outline)
-{
- int count = 0;
-
- while (outline)
- {
- if (outline->dest.kind == FZ_LINK_GOTO
- && outline->dest.ld.gotor.page >= 0
- && outline->title)
- count++;
-
- count += countOutlineItems(outline->down);
- outline = outline->next;
- }
-
- return count;
-}
-
-static int
-fillInOutlineItems(JNIEnv * env, jclass olClass, jmethodID ctor, jobjectArray arr, int pos, fz_outline *outline, int level)
-{
- while (outline)
- {
- if (outline->dest.kind == FZ_LINK_GOTO)
- {
- int page = outline->dest.ld.gotor.page;
- if (page >= 0 && outline->title)
- {
- jobject ol;
- jstring title = (*env)->NewStringUTF(env, outline->title);
- if (title == NULL) return -1;
- ol = (*env)->NewObject(env, olClass, ctor, level, title, page);
- if (ol == NULL) return -1;
- (*env)->SetObjectArrayElement(env, arr, pos, ol);
- (*env)->DeleteLocalRef(env, ol);
- (*env)->DeleteLocalRef(env, title);
- pos++;
- }
- }
- pos = fillInOutlineItems(env, olClass, ctor, arr, pos, outline->down, level+1);
- if (pos < 0) return -1;
- outline = outline->next;
- }
-
- return pos;
-}
-
-JNIEXPORT jboolean JNICALL
-JNI_FN(MuPDFCore_needsPasswordInternal)(JNIEnv * env, jobject thiz)
-{
- globals *glo = get_globals(env, thiz);
-
- return fz_needs_password(glo->doc) ? JNI_TRUE : JNI_FALSE;
-}
-
-JNIEXPORT jboolean JNICALL
-JNI_FN(MuPDFCore_authenticatePasswordInternal)(JNIEnv *env, jobject thiz, jstring password)
-{
- const char *pw;
- int result;
- globals *glo = get_globals(env, thiz);
-
- pw = (*env)->GetStringUTFChars(env, password, NULL);
- if (pw == NULL)
- return JNI_FALSE;
-
- result = fz_authenticate_password(glo->doc, (char *)pw);
- (*env)->ReleaseStringUTFChars(env, password, pw);
- return result;
-}
-
-JNIEXPORT jboolean JNICALL
-JNI_FN(MuPDFCore_hasOutlineInternal)(JNIEnv * env, jobject thiz)
-{
- globals *glo = get_globals(env, thiz);
- fz_outline *outline = fz_load_outline(glo->doc);
-
- fz_free_outline(glo->ctx, outline);
- return (outline == NULL) ? JNI_FALSE : JNI_TRUE;
-}
-
-JNIEXPORT jobjectArray JNICALL
-JNI_FN(MuPDFCore_getOutlineInternal)(JNIEnv * env, jobject thiz)
-{
- jclass olClass;
- jmethodID ctor;
- jobjectArray arr;
- jobject ol;
- fz_outline *outline;
- int nItems;
- globals *glo = get_globals(env, thiz);
- jobjectArray ret;
-
- olClass = (*env)->FindClass(env, PACKAGENAME "/OutlineItem");
- if (olClass == NULL) return NULL;
- ctor = (*env)->GetMethodID(env, olClass, "<init>", "(ILjava/lang/String;I)V");
- if (ctor == NULL) return NULL;
-
- outline = fz_load_outline(glo->doc);
- nItems = countOutlineItems(outline);
-
- arr = (*env)->NewObjectArray(env,
- nItems,
- olClass,
- NULL);
- if (arr == NULL) return NULL;
-
- ret = fillInOutlineItems(env, olClass, ctor, arr, 0, outline, 0) > 0
- ? arr
- :NULL;
- fz_free_outline(glo->ctx, outline);
- return ret;
-}
-
-JNIEXPORT jobjectArray JNICALL
-JNI_FN(MuPDFCore_searchPage)(JNIEnv * env, jobject thiz, jstring jtext)
-{
- jclass rectClass;
- jmethodID ctor;
- jobjectArray arr;
- jobject rect;
- fz_text_sheet *sheet = NULL;
- fz_text_page *text = NULL;
- fz_device *dev = NULL;
- float zoom;
- fz_matrix ctm;
- int pos;
- int len;
- int i, n;
- int hit_count = 0;
- const char *str;
- globals *glo = get_globals(env, thiz);
- fz_context *ctx = glo->ctx;
- fz_document *doc = glo->doc;
- page_cache *pc = &glo->pages[glo->current];
-
- rectClass = (*env)->FindClass(env, "android/graphics/RectF");
- if (rectClass == NULL) return NULL;
- ctor = (*env)->GetMethodID(env, rectClass, "<init>", "(FFFF)V");
- if (ctor == NULL) return NULL;
- str = (*env)->GetStringUTFChars(env, jtext, NULL);
- if (str == NULL) return NULL;
-
- fz_var(sheet);
- fz_var(text);
- fz_var(dev);
-
- fz_try(ctx)
- {
- if (glo->hit_bbox == NULL)
- glo->hit_bbox = fz_malloc_array(ctx, MAX_SEARCH_HITS, sizeof(*glo->hit_bbox));
-
- zoom = glo->resolution / 72;
- fz_scale(&ctm, zoom, zoom);
- sheet = fz_new_text_sheet(ctx);
- text = fz_new_text_page(ctx);
- dev = fz_new_text_device(ctx, sheet, text);
- fz_run_page(doc, pc->page, dev, &ctm, NULL);
- fz_free_device(dev);
- dev = NULL;
-
- hit_count = fz_search_text_page(ctx, text, str, glo->hit_bbox, MAX_SEARCH_HITS);
- }
- fz_always(ctx)
- {
- fz_free_text_page(ctx, text);
- fz_free_text_sheet(ctx, sheet);
- fz_free_device(dev);
- }
- fz_catch(ctx)
- {
- jclass cls;
- (*env)->ReleaseStringUTFChars(env, jtext, str);
- cls = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
- if (cls != NULL)
- (*env)->ThrowNew(env, cls, "Out of memory in MuPDFCore_searchPage");
- (*env)->DeleteLocalRef(env, cls);
-
- return NULL;
- }
-
- (*env)->ReleaseStringUTFChars(env, jtext, str);
-
- arr = (*env)->NewObjectArray(env,
- hit_count,
- rectClass,
- NULL);
- if (arr == NULL) return NULL;
-
- for (i = 0; i < hit_count; i++) {
- rect = (*env)->NewObject(env, rectClass, ctor,
- (float) (glo->hit_bbox[i].x0),
- (float) (glo->hit_bbox[i].y0),
- (float) (glo->hit_bbox[i].x1),
- (float) (glo->hit_bbox[i].y1));
- if (rect == NULL)
- return NULL;
- (*env)->SetObjectArrayElement(env, arr, i, rect);
- (*env)->DeleteLocalRef(env, rect);
- }
-
- return arr;
-}
-
-JNIEXPORT jobjectArray JNICALL
-JNI_FN(MuPDFCore_text)(JNIEnv * env, jobject thiz)
-{
- jclass textCharClass;
- jclass textSpanClass;
- jclass textLineClass;
- jclass textBlockClass;
- jmethodID ctor;
- jobjectArray barr = NULL;
- fz_text_sheet *sheet = NULL;
- fz_text_page *text = NULL;
- fz_device *dev = NULL;
- float zoom;
- fz_matrix ctm;
- globals *glo = get_globals(env, thiz);
- fz_context *ctx = glo->ctx;
- fz_document *doc = glo->doc;
- page_cache *pc = &glo->pages[glo->current];
-
- textCharClass = (*env)->FindClass(env, PACKAGENAME "/TextChar");
- if (textCharClass == NULL) return NULL;
- textSpanClass = (*env)->FindClass(env, "[L" PACKAGENAME "/TextChar;");
- if (textSpanClass == NULL) return NULL;
- textLineClass = (*env)->FindClass(env, "[[L" PACKAGENAME "/TextChar;");
- if (textLineClass == NULL) return NULL;
- textBlockClass = (*env)->FindClass(env, "[[[L" PACKAGENAME "/TextChar;");
- if (textBlockClass == NULL) return NULL;
- ctor = (*env)->GetMethodID(env, textCharClass, "<init>", "(FFFFC)V");
- if (ctor == NULL) return NULL;
-
- fz_var(sheet);
- fz_var(text);
- fz_var(dev);
-
- fz_try(ctx)
- {
- int b, l, s, c;
-
- zoom = glo->resolution / 72;
- fz_scale(&ctm, zoom, zoom);
- sheet = fz_new_text_sheet(ctx);
- text = fz_new_text_page(ctx);
- dev = fz_new_text_device(ctx, sheet, text);
- fz_run_page(doc, pc->page, dev, &ctm, NULL);
- fz_free_device(dev);
- dev = NULL;
-
- barr = (*env)->NewObjectArray(env, text->len, textBlockClass, NULL);
- if (barr == NULL) fz_throw(ctx, FZ_ERROR_GENERIC, "NewObjectArray failed");
-
- for (b = 0; b < text->len; b++)
- {
- fz_text_block *block;
- jobjectArray *larr;
-
- if (text->blocks[b].type != FZ_PAGE_BLOCK_TEXT)
- continue;
- block = text->blocks[b].u.text;
- larr = (*env)->NewObjectArray(env, block->len, textLineClass, NULL);
- if (larr == NULL) fz_throw(ctx, FZ_ERROR_GENERIC, "NewObjectArray failed");
-
- for (l = 0; l < block->len; l++)
- {
- fz_text_line *line = &block->lines[l];
- jobjectArray *sarr;
- fz_text_span *span;
- int len = 0;
-
- for (span = line->first_span; span; span = span->next)
- len++;
-
- sarr = (*env)->NewObjectArray(env, len, textSpanClass, NULL);
- if (sarr == NULL) fz_throw(ctx, FZ_ERROR_GENERIC, "NewObjectArray failed");
-
- for (s=0, span = line->first_span; span; s++, span = span->next)
- {
- jobjectArray *carr = (*env)->NewObjectArray(env, span->len, textCharClass, NULL);
- if (carr == NULL) fz_throw(ctx, FZ_ERROR_GENERIC, "NewObjectArray failed");
-
- for (c = 0; c < span->len; c++)
- {
- fz_text_char *ch = &span->text[c];
- fz_rect bbox;
- fz_text_char_bbox(&bbox, span, c);
- jobject cobj = (*env)->NewObject(env, textCharClass, ctor, bbox.x0, bbox.y0, bbox.x1, bbox.y1, ch->c);
- if (cobj == NULL) fz_throw(ctx, FZ_ERROR_GENERIC, "NewObjectfailed");
-
- (*env)->SetObjectArrayElement(env, carr, c, cobj);
- (*env)->DeleteLocalRef(env, cobj);
- }
-
- (*env)->SetObjectArrayElement(env, sarr, s, carr);
- (*env)->DeleteLocalRef(env, carr);
- }
-
- (*env)->SetObjectArrayElement(env, larr, l, sarr);
- (*env)->DeleteLocalRef(env, sarr);
- }
-
- (*env)->SetObjectArrayElement(env, barr, b, larr);
- (*env)->DeleteLocalRef(env, larr);
- }
- }
- fz_always(ctx)
- {
- fz_free_text_page(ctx, text);
- fz_free_text_sheet(ctx, sheet);
- fz_free_device(dev);
- }
- fz_catch(ctx)
- {
- jclass cls = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
- if (cls != NULL)
- (*env)->ThrowNew(env, cls, "Out of memory in MuPDFCore_text");
- (*env)->DeleteLocalRef(env, cls);
-
- return NULL;
- }
-
- return barr;
-}
-
-JNIEXPORT jbyteArray JNICALL
-JNI_FN(MuPDFCore_textAsHtml)(JNIEnv * env, jobject thiz)
-{
- fz_text_sheet *sheet = NULL;
- fz_text_page *text = NULL;
- fz_device *dev = NULL;
- fz_matrix ctm;
- globals *glo = get_globals(env, thiz);
- fz_context *ctx = glo->ctx;
- fz_document *doc = glo->doc;
- page_cache *pc = &glo->pages[glo->current];
- jbyteArray bArray = NULL;
- fz_buffer *buf = NULL;
- fz_output *out = NULL;
-
- fz_var(sheet);
- fz_var(text);
- fz_var(dev);
-
- fz_try(ctx)
- {
- int b, l, s, c;
-
- ctm = fz_identity;
- sheet = fz_new_text_sheet(ctx);
- text = fz_new_text_page(ctx);
- dev = fz_new_text_device(ctx, sheet, text);
- fz_run_page(doc, pc->page, dev, &ctm, NULL);
- fz_free_device(dev);
- dev = NULL;
-
- fz_analyze_text(ctx, sheet, text);
-
- buf = fz_new_buffer(ctx, 256);
- out = fz_new_output_with_buffer(ctx, buf);
- fz_printf(out, "<html>\n");
- fz_printf(out, "<style>\n");
- fz_printf(out, "body{margin:0;}\n");
- fz_printf(out, "div.page{background-color:white;}\n");
- fz_printf(out, "div.block{margin:0pt;padding:0pt;}\n");
- fz_printf(out, "div.metaline{display:table;width:100%%}\n");
- fz_printf(out, "div.line{display:table-row;}\n");
- fz_printf(out, "div.cell{display:table-cell;padding-left:0.25em;padding-right:0.25em}\n");
- //fz_printf(out, "p{margin:0;padding:0;}\n");
- fz_printf(out, "</style>\n");
- fz_printf(out, "<body style=\"margin:0\"><div style=\"padding:10px\" id=\"content\">");
- fz_print_text_page_html(ctx, out, text);
- fz_printf(out, "</div></body>\n");
- fz_printf(out, "<style>\n");
- fz_print_text_sheet(ctx, out, sheet);
- fz_printf(out, "</style>\n</html>\n");
- fz_close_output(out);
- out = NULL;
-
- bArray = (*env)->NewByteArray(env, buf->len);
- if (bArray == NULL)
- fz_throw(ctx, FZ_ERROR_GENERIC, "Failed to make byteArray");
- (*env)->SetByteArrayRegion(env, bArray, 0, buf->len, buf->data);
-
- }
- fz_always(ctx)
- {
- fz_free_text_page(ctx, text);
- fz_free_text_sheet(ctx, sheet);
- fz_free_device(dev);
- fz_close_output(out);
- fz_drop_buffer(ctx, buf);
- }
- fz_catch(ctx)
- {
- jclass cls = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
- if (cls != NULL)
- (*env)->ThrowNew(env, cls, "Out of memory in MuPDFCore_textAsHtml");
- (*env)->DeleteLocalRef(env, cls);
-
- return NULL;
- }
-
- return bArray;
-}
-
-JNIEXPORT void JNICALL
-JNI_FN(MuPDFCore_addMarkupAnnotationInternal)(JNIEnv * env, jobject thiz, jobjectArray points, fz_annot_type type)
-{
- globals *glo = get_globals(env, thiz);
- fz_context *ctx = glo->ctx;
- fz_document *doc = glo->doc;
- pdf_document *idoc = pdf_specifics(doc);
- page_cache *pc = &glo->pages[glo->current];
- jclass pt_cls;
- jfieldID x_fid, y_fid;
- int i, n;
- fz_point *pts = NULL;
- float color[3];
- float alpha;
- float line_height;
- float line_thickness;
-
- if (idoc == NULL)
- return;
-
- switch (type)
- {
- case FZ_ANNOT_HIGHLIGHT:
- color[0] = 1.0;
- color[1] = 1.0;
- color[2] = 0.0;
- alpha = 0.5;
- line_thickness = 1.0;
- line_height = 0.5;
- break;
- case FZ_ANNOT_UNDERLINE:
- color[0] = 0.0;
- color[1] = 0.0;
- color[2] = 1.0;
- alpha = 1.0;
- line_thickness = LINE_THICKNESS;
- line_height = UNDERLINE_HEIGHT;
- break;
- case FZ_ANNOT_STRIKEOUT:
- color[0] = 1.0;
- color[1] = 0.0;
- color[2] = 0.0;
- alpha = 1.0;
- line_thickness = LINE_THICKNESS;
- line_height = STRIKE_HEIGHT;
- break;
- default:
- return;
- }
-
- fz_var(pts);
- fz_try(ctx)
- {
- fz_annot *annot;
- fz_matrix ctm;
-
- float zoom = glo->resolution / 72;
- zoom = 1.0 / zoom;
- fz_scale(&ctm, zoom, zoom);
- pt_cls = (*env)->FindClass(env, "android.graphics.PointF");
- if (pt_cls == NULL) fz_throw(ctx, FZ_ERROR_GENERIC, "FindClass");
- x_fid = (*env)->GetFieldID(env, pt_cls, "x", "F");
- if (x_fid == NULL) fz_throw(ctx, FZ_ERROR_GENERIC, "GetFieldID(x)");
- y_fid = (*env)->GetFieldID(env, pt_cls, "y", "F");
- if (y_fid == NULL) fz_throw(ctx, FZ_ERROR_GENERIC, "GetFieldID(y)");
-
- n = (*env)->GetArrayLength(env, points);
-
- pts = fz_malloc_array(ctx, n, sizeof(fz_point));
-
- for (i = 0; i < n; i++)
- {
- jobject opt = (*env)->GetObjectArrayElement(env, points, i);
- pts[i].x = opt ? (*env)->GetFloatField(env, opt, x_fid) : 0.0f;
- pts[i].y = opt ? (*env)->GetFloatField(env, opt, y_fid) : 0.0f;
- fz_transform_point(&pts[i], &ctm);
- }
-
- annot = (fz_annot *)pdf_create_annot(idoc, (pdf_page *)pc->page, type);
-
- pdf_set_markup_annot_quadpoints(idoc, (pdf_annot *)annot, pts, n);
- pdf_set_markup_appearance(idoc, (pdf_annot *)annot, color, alpha, line_thickness, line_height);
-
- dump_annotation_display_lists(glo);
- }
- fz_always(ctx)
- {
- fz_free(ctx, pts);
- }
- fz_catch(ctx)
- {
- LOGE("addStrikeOutAnnotation: %s failed", ctx->error->message);
- jclass cls = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
- if (cls != NULL)
- (*env)->ThrowNew(env, cls, "Out of memory in MuPDFCore_searchPage");
- (*env)->DeleteLocalRef(env, cls);
- }
-}
-
-JNIEXPORT void JNICALL
-JNI_FN(MuPDFCore_addInkAnnotationInternal)(JNIEnv * env, jobject thiz, jobjectArray arcs)
-{
- globals *glo = get_globals(env, thiz);
- fz_context *ctx = glo->ctx;
- fz_document *doc = glo->doc;
- pdf_document *idoc = pdf_specifics(doc);
- page_cache *pc = &glo->pages[glo->current];
- jclass pt_cls;
- jfieldID x_fid, y_fid;
- int i, j, k, n;
- fz_point *pts = NULL;
- int *counts = NULL;
- int total = 0;
- float color[3];
-
- if (idoc == NULL)
- return;
-
- color[0] = 1.0;
- color[1] = 0.0;
- color[2] = 0.0;
-
- fz_var(pts);
- fz_var(counts);
- fz_try(ctx)
- {
- fz_annot *annot;
- fz_matrix ctm;
-
- float zoom = glo->resolution / 72;
- zoom = 1.0 / zoom;
- fz_scale(&ctm, zoom, zoom);
- pt_cls = (*env)->FindClass(env, "android.graphics.PointF");
- if (pt_cls == NULL) fz_throw(ctx, FZ_ERROR_GENERIC, "FindClass");
- x_fid = (*env)->GetFieldID(env, pt_cls, "x", "F");
- if (x_fid == NULL) fz_throw(ctx, FZ_ERROR_GENERIC, "GetFieldID(x)");
- y_fid = (*env)->GetFieldID(env, pt_cls, "y", "F");
- if (y_fid == NULL) fz_throw(ctx, FZ_ERROR_GENERIC, "GetFieldID(y)");
-
- n = (*env)->GetArrayLength(env, arcs);
-
- counts = fz_malloc_array(ctx, n, sizeof(int));
-
- for (i = 0; i < n; i++)
- {
- jobjectArray arc = (jobjectArray)(*env)->GetObjectArrayElement(env, arcs, i);
- int count = (*env)->GetArrayLength(env, arc);
-
- counts[i] = count;
- total += count;
- }
-
- pts = fz_malloc_array(ctx, total, sizeof(fz_point));
-
- k = 0;
- for (i = 0; i < n; i++)
- {
- jobjectArray arc = (jobjectArray)(*env)->GetObjectArrayElement(env, arcs, i);
- int count = counts[i];
-
- for (j = 0; j < count; j++)
- {
- jobject pt = (*env)->GetObjectArrayElement(env, arc, j);
-
- pts[k].x = pt ? (*env)->GetFloatField(env, pt, x_fid) : 0.0f;
- pts[k].y = pt ? (*env)->GetFloatField(env, pt, y_fid) : 0.0f;
- fz_transform_point(&pts[k], &ctm);
- k++;
- }
- }
-
- annot = (fz_annot *)pdf_create_annot(idoc, (pdf_page *)pc->page, FZ_ANNOT_INK);
-
- pdf_set_ink_annot_list(idoc, (pdf_annot *)annot, pts, counts, n, color, INK_THICKNESS);
-
- dump_annotation_display_lists(glo);
- }
- fz_always(ctx)
- {
- fz_free(ctx, pts);
- fz_free(ctx, counts);
- }
- fz_catch(ctx)
- {
- LOGE("addInkAnnotation: %s failed", ctx->error->message);
- jclass cls = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
- if (cls != NULL)
- (*env)->ThrowNew(env, cls, "Out of memory in MuPDFCore_searchPage");
- (*env)->DeleteLocalRef(env, cls);
- }
-}
-
-JNIEXPORT void JNICALL
-JNI_FN(MuPDFCore_deleteAnnotationInternal)(JNIEnv * env, jobject thiz, int annot_index)
-{
- globals *glo = get_globals(env, thiz);
- fz_context *ctx = glo->ctx;
- fz_document *doc = glo->doc;
- pdf_document *idoc = pdf_specifics(doc);
- page_cache *pc = &glo->pages[glo->current];
- fz_annot *annot;
- int i;
-
- if (idoc == NULL)
- return;
-
- fz_try(ctx)
- {
- annot = fz_first_annot(glo->doc, pc->page);
- for (i = 0; i < annot_index && annot; i++)
- annot = fz_next_annot(glo->doc, annot);
-
- if (annot)
- {
- pdf_delete_annot(idoc, (pdf_page *)pc->page, (pdf_annot *)annot);
- dump_annotation_display_lists(glo);
- }
- }
- fz_catch(ctx)
- {
- LOGE("deleteAnnotationInternal: %s", ctx->error->message);
- }
-}
-
-/* Close the document, at least enough to be able to save over it. This
- * may be called again later, so must be idempotent. */
-static void close_doc(globals *glo)
-{
- int i;
-
- fz_free(glo->ctx, glo->hit_bbox);
- glo->hit_bbox = NULL;
-
- for (i = 0; i < NUM_CACHE; i++)
- drop_page_cache(glo, &glo->pages[i]);
-
- alerts_fin(glo);
-
- fz_close_document(glo->doc);
- glo->doc = NULL;
-}
-
-JNIEXPORT void JNICALL
-JNI_FN(MuPDFCore_destroying)(JNIEnv * env, jobject thiz)
-{
- globals *glo = get_globals(env, thiz);
-
- if (glo == NULL)
- return;
- LOGI("Destroying");
- fz_free(glo->ctx, glo->current_path);
- glo->current_path = NULL;
- close_doc(glo);
- fz_free_context(glo->ctx);
- glo->ctx = NULL;
- free(glo);
-#ifdef MEMENTO
- LOGI("Destroying dump start");
- Memento_listBlocks();
- Memento_stats();
- LOGI("Destroying dump end");
-#endif
-#ifdef NDK_PROFILER
- // Apparently we should really be writing to whatever path we get
- // from calling getFilesDir() in the java part, which supposedly
- // gives /sdcard/data/data/com.artifex.MuPDF/gmon.out, but that's
- // unfriendly.
- setenv("CPUPROFILE", "/sdcard/gmon.out", 1);
- moncleanup();
-#endif
-}
-
-JNIEXPORT jobjectArray JNICALL
-JNI_FN(MuPDFCore_getPageLinksInternal)(JNIEnv * env, jobject thiz, int pageNumber)
-{
- jclass linkInfoClass;
- jclass linkInfoInternalClass;
- jclass linkInfoExternalClass;
- jclass linkInfoRemoteClass;
- jmethodID ctorInternal;
- jmethodID ctorExternal;
- jmethodID ctorRemote;
- jobjectArray arr;
- jobject linkInfo;
- fz_matrix ctm;
- float zoom;
- fz_link *list;
- fz_link *link;
- int count;
- page_cache *pc;
- globals *glo = get_globals(env, thiz);
-
- linkInfoClass = (*env)->FindClass(env, PACKAGENAME "/LinkInfo");
- if (linkInfoClass == NULL) return NULL;
- linkInfoInternalClass = (*env)->FindClass(env, PACKAGENAME "/LinkInfoInternal");
- if (linkInfoInternalClass == NULL) return NULL;
- linkInfoExternalClass = (*env)->FindClass(env, PACKAGENAME "/LinkInfoExternal");
- if (linkInfoExternalClass == NULL) return NULL;
- linkInfoRemoteClass = (*env)->FindClass(env, PACKAGENAME "/LinkInfoRemote");
- if (linkInfoRemoteClass == NULL) return NULL;
- ctorInternal = (*env)->GetMethodID(env, linkInfoInternalClass, "<init>", "(FFFFI)V");
- if (ctorInternal == NULL) return NULL;
- ctorExternal = (*env)->GetMethodID(env, linkInfoExternalClass, "<init>", "(FFFFLjava/lang/String;)V");
- if (ctorExternal == NULL) return NULL;
- ctorRemote = (*env)->GetMethodID(env, linkInfoRemoteClass, "<init>", "(FFFFLjava/lang/String;IZ)V");
- if (ctorRemote == NULL) return NULL;
-
- JNI_FN(MuPDFCore_gotoPageInternal)(env, thiz, pageNumber);
- pc = &glo->pages[glo->current];
- if (pc->page == NULL || pc->number != pageNumber)
- return NULL;
-
- zoom = glo->resolution / 72;
- fz_scale(&ctm, zoom, zoom);
-
- list = fz_load_links(glo->doc, pc->page);
- count = 0;
- for (link = list; link; link = link->next)
- {
- switch (link->dest.kind)
- {
- case FZ_LINK_GOTO:
- case FZ_LINK_GOTOR:
- case FZ_LINK_URI:
- count++ ;
- }
- }
-
- arr = (*env)->NewObjectArray(env, count, linkInfoClass, NULL);
- if (arr == NULL)
- {
- fz_drop_link(glo->ctx, list);
- return NULL;
- }
-
- count = 0;
- for (link = list; link; link = link->next)
- {
- fz_rect rect = link->rect;
- fz_transform_rect(&rect, &ctm);
-
- switch (link->dest.kind)
- {
- case FZ_LINK_GOTO:
- {
- linkInfo = (*env)->NewObject(env, linkInfoInternalClass, ctorInternal,
- (float)rect.x0, (float)rect.y0, (float)rect.x1, (float)rect.y1,
- link->dest.ld.gotor.page);
- break;
- }
-
- case FZ_LINK_GOTOR:
- {
- jstring juri = (*env)->NewStringUTF(env, link->dest.ld.gotor.file_spec);
- linkInfo = (*env)->NewObject(env, linkInfoRemoteClass, ctorRemote,
- (float)rect.x0, (float)rect.y0, (float)rect.x1, (float)rect.y1,
- juri, link->dest.ld.gotor.page, link->dest.ld.gotor.new_window ? JNI_TRUE : JNI_FALSE);
- break;
- }
-
- case FZ_LINK_URI:
- {
- jstring juri = (*env)->NewStringUTF(env, link->dest.ld.uri.uri);
- linkInfo = (*env)->NewObject(env, linkInfoExternalClass, ctorExternal,
- (float)rect.x0, (float)rect.y0, (float)rect.x1, (float)rect.y1,
- juri);
- break;
- }
-
- default:
- continue;
- }
-
- if (linkInfo == NULL)
- {
- fz_drop_link(glo->ctx, list);
- return NULL;
- }
- (*env)->SetObjectArrayElement(env, arr, count, linkInfo);
- (*env)->DeleteLocalRef(env, linkInfo);
- count++;
- }
- fz_drop_link(glo->ctx, list);
-
- return arr;
-}
-
-JNIEXPORT jobjectArray JNICALL
-JNI_FN(MuPDFCore_getWidgetAreasInternal)(JNIEnv * env, jobject thiz, int pageNumber)
-{
- jclass rectFClass;
- jmethodID ctor;
- jobjectArray arr;
- jobject rectF;
- pdf_document *idoc;
- pdf_widget *widget;
- fz_matrix ctm;
- float zoom;
- int count;
- page_cache *pc;
- globals *glo = get_globals(env, thiz);
-
- 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;
-
- JNI_FN(MuPDFCore_gotoPageInternal)(env, thiz, pageNumber);
- pc = &glo->pages[glo->current];
- if (pc->number != pageNumber || pc->page == NULL)
- return NULL;
-
- idoc = pdf_specifics(glo->doc);
- if (idoc == NULL)
- return NULL;
-
- zoom = glo->resolution / 72;
- fz_scale(&ctm, zoom, zoom);
-
- count = 0;
- for (widget = pdf_first_widget(idoc, (pdf_page *)pc->page); widget; widget = pdf_next_widget(widget))
- count ++;
-
- arr = (*env)->NewObjectArray(env, count, rectFClass, NULL);
- if (arr == NULL) return NULL;
-
- count = 0;
- for (widget = pdf_first_widget(idoc, (pdf_page *)pc->page); widget; widget = pdf_next_widget(widget))
- {
- fz_rect rect;
- pdf_bound_widget(widget, &rect);
- fz_transform_rect(&rect, &ctm);
-
- 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 jobjectArray JNICALL
-JNI_FN(MuPDFCore_getAnnotationsInternal)(JNIEnv * env, jobject thiz, int pageNumber)
-{
- jclass annotClass;
- jmethodID ctor;
- jobjectArray arr;
- jobject jannot;
- fz_annot *annot;
- fz_matrix ctm;
- float zoom;
- int count;
- page_cache *pc;
- globals *glo = get_globals(env, thiz);
-
- annotClass = (*env)->FindClass(env, PACKAGENAME "/Annotation");
- if (annotClass == NULL) return NULL;
- ctor = (*env)->GetMethodID(env, annotClass, "<init>", "(FFFFI)V");
- if (ctor == NULL) return NULL;
-
- JNI_FN(MuPDFCore_gotoPageInternal)(env, thiz, pageNumber);
- pc = &glo->pages[glo->current];
- if (pc->number != pageNumber || pc->page == NULL)
- return NULL;
-
- zoom = glo->resolution / 72;
- fz_scale(&ctm, zoom, zoom);
-
- count = 0;
- for (annot = fz_first_annot(glo->doc, pc->page); annot; annot = fz_next_annot(glo->doc, annot))
- count ++;
-
- arr = (*env)->NewObjectArray(env, count, annotClass, NULL);
- if (arr == NULL) return NULL;
-
- count = 0;
- for (annot = fz_first_annot(glo->doc, pc->page); annot; annot = fz_next_annot(glo->doc, annot))
- {
- fz_rect rect;
- fz_annot_type type = pdf_annot_type((pdf_annot *)annot);
- fz_bound_annot(glo->doc, annot, &rect);
- fz_transform_rect(&rect, &ctm);
-
- jannot = (*env)->NewObject(env, annotClass, ctor,
- (float)rect.x0, (float)rect.y0, (float)rect.x1, (float)rect.y1, type);
- if (jannot == NULL) return NULL;
- (*env)->SetObjectArrayElement(env, arr, count, jannot);
- (*env)->DeleteLocalRef(env, jannot);
-
- count ++;
- }
-
- return arr;
-}
-
-JNIEXPORT int JNICALL
-JNI_FN(MuPDFCore_passClickEventInternal)(JNIEnv * env, jobject thiz, int pageNumber, float x, float y)
-{
- globals *glo = get_globals(env, thiz);
- fz_context *ctx = glo->ctx;
- fz_matrix ctm;
- pdf_document *idoc = pdf_specifics(glo->doc);
- float zoom;
- fz_point p;
- pdf_ui_event event;
- int changed = 0;
- page_cache *pc;
-
- if (idoc == NULL)
- return 0;
-
- JNI_FN(MuPDFCore_gotoPageInternal)(env, thiz, pageNumber);
- pc = &glo->pages[glo->current];
- if (pc->number != pageNumber || pc->page == 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 = glo->resolution / 72;
- fz_scale(&ctm, zoom, zoom);
- fz_invert_matrix(&ctm, &ctm);
-
- fz_transform_point(&p, &ctm);
-
- fz_try(ctx)
- {
- event.etype = PDF_EVENT_TYPE_POINTER;
- event.event.pointer.pt = p;
- event.event.pointer.ptype = PDF_POINTER_DOWN;
- changed = pdf_pass_event(idoc, (pdf_page *)pc->page, &event);
- event.event.pointer.ptype = PDF_POINTER_UP;
- changed |= pdf_pass_event(idoc, (pdf_page *)pc->page, &event);
- if (changed) {
- dump_annotation_display_lists(glo);
- }
- }
- fz_catch(ctx)
- {
- LOGE("passClickEvent: %s", ctx->error->message);
- }
-
- return changed;
-}
-
-JNIEXPORT jstring JNICALL
-JNI_FN(MuPDFCore_getFocusedWidgetTextInternal)(JNIEnv * env, jobject thiz)
-{
- char *text = "";
- globals *glo = get_globals(env, thiz);
- fz_context *ctx = glo->ctx;
-
- fz_try(ctx)
- {
- pdf_document *idoc = pdf_specifics(glo->doc);
-
- if (idoc)
- {
- pdf_widget *focus = pdf_focused_widget(idoc);
-
- if (focus)
- text = pdf_text_widget_text(idoc, focus);
- }
- }
- fz_catch(ctx)
- {
- LOGE("getFocusedWidgetText failed: %s", ctx->error->message);
- }
-
- return (*env)->NewStringUTF(env, text);
-}
-
-JNIEXPORT int JNICALL
-JNI_FN(MuPDFCore_setFocusedWidgetTextInternal)(JNIEnv * env, jobject thiz, jstring jtext)
-{
- const char *text;
- int result = 0;
- globals *glo = get_globals(env, thiz);
- fz_context *ctx = glo->ctx;
-
- text = (*env)->GetStringUTFChars(env, jtext, NULL);
- if (text == NULL)
- {
- LOGE("Failed to get text");
- return 0;
- }
-
- fz_try(ctx)
- {
- pdf_document *idoc = pdf_specifics(glo->doc);
-
- if (idoc)
- {
- pdf_widget *focus = pdf_focused_widget(idoc);
-
- if (focus)
- {
- result = pdf_text_widget_set_text(idoc, focus, (char *)text);
- dump_annotation_display_lists(glo);
- }
- }
- }
- fz_catch(ctx)
- {
- LOGE("setFocusedWidgetText failed: %s", ctx->error->message);
- }
-
- (*env)->ReleaseStringUTFChars(env, jtext, text);
-
- return result;
-}
-
-JNIEXPORT jobjectArray JNICALL
-JNI_FN(MuPDFCore_getFocusedWidgetChoiceOptions)(JNIEnv * env, jobject thiz)
-{
- globals *glo = get_globals(env, thiz);
- fz_context *ctx = glo->ctx;
- pdf_document *idoc = pdf_specifics(glo->doc);
- pdf_widget *focus;
- int type;
- int nopts, i;
- char **opts = NULL;
- jclass stringClass;
- jobjectArray arr;
-
- if (idoc == NULL)
- return NULL;
-
- focus = pdf_focused_widget(idoc);
- if (focus == NULL)
- return NULL;
-
- type = pdf_widget_get_type(focus);
- if (type != PDF_WIDGET_TYPE_LISTBOX && type != PDF_WIDGET_TYPE_COMBOBOX)
- return NULL;
-
- fz_var(opts);
- fz_try(ctx)
- {
- nopts = pdf_choice_widget_options(idoc, focus, NULL);
- opts = fz_malloc(ctx, nopts * sizeof(*opts));
- (void)pdf_choice_widget_options(idoc, focus, opts);
- }
- fz_catch(ctx)
- {
- fz_free(ctx, opts);
- LOGE("Failed in getFocuseedWidgetChoiceOptions");
- return NULL;
- }
-
- stringClass = (*env)->FindClass(env, "java/lang/String");
-
- arr = (*env)->NewObjectArray(env, nopts, stringClass, NULL);
-
- for (i = 0; i < nopts; i++)
- {
- jstring s = (*env)->NewStringUTF(env, opts[i]);
- if (s != NULL)
- (*env)->SetObjectArrayElement(env, arr, i, s);
-
- (*env)->DeleteLocalRef(env, s);
- }
-
- fz_free(ctx, opts);
-
- return arr;
-}
-
-JNIEXPORT jobjectArray JNICALL
-JNI_FN(MuPDFCore_getFocusedWidgetChoiceSelected)(JNIEnv * env, jobject thiz)
-{
- globals *glo = get_globals(env, thiz);
- fz_context *ctx = glo->ctx;
- pdf_document *idoc = pdf_specifics(glo->doc);
- pdf_widget *focus;
- int type;
- int nsel, i;
- char **sel = NULL;
- jclass stringClass;
- jobjectArray arr;
-
- if (idoc == NULL)
- return NULL;
-
- focus = pdf_focused_widget(idoc);
- if (focus == NULL)
- return NULL;
-
- type = pdf_widget_get_type(focus);
- if (type != PDF_WIDGET_TYPE_LISTBOX && type != PDF_WIDGET_TYPE_COMBOBOX)
- return NULL;
-
- fz_var(sel);
- fz_try(ctx)
- {
- nsel = pdf_choice_widget_value(idoc, focus, NULL);
- sel = fz_malloc(ctx, nsel * sizeof(*sel));
- (void)pdf_choice_widget_value(idoc, focus, sel);
- }
- fz_catch(ctx)
- {
- fz_free(ctx, sel);
- LOGE("Failed in getFocuseedWidgetChoiceOptions");
- return NULL;
- }
-
- stringClass = (*env)->FindClass(env, "java/lang/String");
-
- arr = (*env)->NewObjectArray(env, nsel, stringClass, NULL);
-
- for (i = 0; i < nsel; i++)
- {
- jstring s = (*env)->NewStringUTF(env, sel[i]);
- if (s != NULL)
- (*env)->SetObjectArrayElement(env, arr, i, s);
-
- (*env)->DeleteLocalRef(env, s);
- }
-
- fz_free(ctx, sel);
-
- return arr;
-}
-
-JNIEXPORT void JNICALL
-JNI_FN(MuPDFCore_setFocusedWidgetChoiceSelectedInternal)(JNIEnv * env, jobject thiz, jobjectArray arr)
-{
- globals *glo = get_globals(env, thiz);
- fz_context *ctx = glo->ctx;
- pdf_document *idoc = pdf_specifics(glo->doc);
- pdf_widget *focus;
- int type;
- int nsel, i;
- char **sel = NULL;
- jstring *objs = NULL;
-
- if (idoc == NULL)
- return;
-
- focus = pdf_focused_widget(idoc);
- if (focus == NULL)
- return;
-
- type = pdf_widget_get_type(focus);
- if (type != PDF_WIDGET_TYPE_LISTBOX && type != PDF_WIDGET_TYPE_COMBOBOX)
- return;
-
- nsel = (*env)->GetArrayLength(env, arr);
-
- sel = calloc(nsel, sizeof(*sel));
- objs = calloc(nsel, sizeof(*objs));
- if (objs == NULL || sel == NULL)
- {
- free(sel);
- free(objs);
- LOGE("Failed in setFocusWidgetChoiceSelected");
- return;
- }
-
- for (i = 0; i < nsel; i++)
- {
- objs[i] = (jstring)(*env)->GetObjectArrayElement(env, arr, i);
- sel[i] = (char *)(*env)->GetStringUTFChars(env, objs[i], NULL);
- }
-
- fz_try(ctx)
- {
- pdf_choice_widget_set_value(idoc, focus, nsel, sel);
- dump_annotation_display_lists(glo);
- }
- fz_catch(ctx)
- {
- LOGE("Failed in setFocusWidgetChoiceSelected");
- }
-
- for (i = 0; i < nsel; i++)
- (*env)->ReleaseStringUTFChars(env, objs[i], sel[i]);
-
- free(sel);
- free(objs);
-}
-
-JNIEXPORT int JNICALL
-JNI_FN(MuPDFCore_getFocusedWidgetTypeInternal)(JNIEnv * env, jobject thiz)
-{
- globals *glo = get_globals(env, thiz);
- pdf_document *idoc = pdf_specifics(glo->doc);
- pdf_widget *focus;
-
- if (idoc == NULL)
- return NONE;
-
- focus = pdf_focused_widget(idoc);
-
- if (focus == NULL)
- return NONE;
-
- switch (pdf_widget_get_type(focus))
- {
- case PDF_WIDGET_TYPE_TEXT: return TEXT;
- case PDF_WIDGET_TYPE_LISTBOX: return LISTBOX;
- case PDF_WIDGET_TYPE_COMBOBOX: return COMBOBOX;
- }
-
- return NONE;
-}
-
-JNIEXPORT jobject JNICALL
-JNI_FN(MuPDFCore_waitForAlertInternal)(JNIEnv * env, jobject thiz)
-{
- globals *glo = get_globals(env, thiz);
- jclass alertClass;
- jmethodID ctor;
- jstring title;
- jstring message;
- int alert_present;
- pdf_alert_event alert;
-
- LOGT("Enter waitForAlert");
- pthread_mutex_lock(&glo->fin_lock);
- pthread_mutex_lock(&glo->alert_lock);
-
- while (glo->alerts_active && !glo->alert_request)
- pthread_cond_wait(&glo->alert_request_cond, &glo->alert_lock);
- glo->alert_request = 0;
-
- alert_present = (glo->alerts_active && glo->current_alert);
-
- if (alert_present)
- alert = *glo->current_alert;
-
- pthread_mutex_unlock(&glo->alert_lock);
- pthread_mutex_unlock(&glo->fin_lock);
- LOGT("Exit waitForAlert %d", alert_present);
-
- if (!alert_present)
- return NULL;
-
- alertClass = (*env)->FindClass(env, PACKAGENAME "/MuPDFAlertInternal");
- if (alertClass == NULL)
- return NULL;
-
- ctor = (*env)->GetMethodID(env, alertClass, "<init>", "(Ljava/lang/String;IILjava/lang/String;I)V");
- if (ctor == NULL)
- return NULL;
-
- title = (*env)->NewStringUTF(env, alert.title);
- if (title == NULL)
- return NULL;
-
- message = (*env)->NewStringUTF(env, alert.message);
- if (message == NULL)
- return NULL;
-
- return (*env)->NewObject(env, alertClass, ctor, message, alert.icon_type, alert.button_group_type, title, alert.button_pressed);
-}
-
-JNIEXPORT void JNICALL
-JNI_FN(MuPDFCore_replyToAlertInternal)(JNIEnv * env, jobject thiz, jobject alert)
-{
- globals *glo = get_globals(env, thiz);
- jclass alertClass;
- jfieldID field;
- int button_pressed;
-
- alertClass = (*env)->FindClass(env, PACKAGENAME "/MuPDFAlertInternal");
- if (alertClass == NULL)
- return;
-
- field = (*env)->GetFieldID(env, alertClass, "buttonPressed", "I");
- if (field == NULL)
- return;
-
- button_pressed = (*env)->GetIntField(env, alert, field);
-
- LOGT("Enter replyToAlert");
- pthread_mutex_lock(&glo->alert_lock);
-
- if (glo->alerts_active && glo->current_alert)
- {
- // Fill in button_pressed and signal reply received.
- glo->current_alert->button_pressed = button_pressed;
- glo->alert_reply = 1;
- pthread_cond_signal(&glo->alert_reply_cond);
- }
-
- pthread_mutex_unlock(&glo->alert_lock);
- LOGT("Exit replyToAlert");
-}
-
-JNIEXPORT void JNICALL
-JNI_FN(MuPDFCore_startAlertsInternal)(JNIEnv * env, jobject thiz)
-{
- globals *glo = get_globals(env, thiz);
-
- if (!glo->alerts_initialised)
- return;
-
- LOGT("Enter startAlerts");
- pthread_mutex_lock(&glo->alert_lock);
-
- glo->alert_reply = 0;
- glo->alert_request = 0;
- glo->alerts_active = 1;
- glo->current_alert = NULL;
-
- pthread_mutex_unlock(&glo->alert_lock);
- LOGT("Exit startAlerts");
-}
-
-JNIEXPORT void JNICALL
-JNI_FN(MuPDFCore_stopAlertsInternal)(JNIEnv * env, jobject thiz)
-{
- globals *glo = get_globals(env, thiz);
-
- if (!glo->alerts_initialised)
- return;
-
- LOGT("Enter stopAlerts");
- pthread_mutex_lock(&glo->alert_lock);
-
- glo->alert_reply = 0;
- glo->alert_request = 0;
- glo->alerts_active = 0;
- glo->current_alert = NULL;
- pthread_cond_signal(&glo->alert_reply_cond);
- pthread_cond_signal(&glo->alert_request_cond);
-
- pthread_mutex_unlock(&glo->alert_lock);
- LOGT("Exit stopAleerts");
-}
-
-JNIEXPORT jboolean JNICALL
-JNI_FN(MuPDFCore_hasChangesInternal)(JNIEnv * env, jobject thiz)
-{
- globals *glo = get_globals(env, thiz);
- pdf_document *idoc = pdf_specifics(glo->doc);
-
- return (idoc && pdf_has_unsaved_changes(idoc)) ? JNI_TRUE : JNI_FALSE;
-}
-
-static char *tmp_path(char *path)
-{
- int f;
- char *buf = malloc(strlen(path) + 6 + 1);
- if (!buf)
- return NULL;
-
- strcpy(buf, path);
- strcat(buf, "XXXXXX");
-
- f = mkstemp(buf);
-
- if (f >= 0)
- {
- close(f);
- return buf;
- }
- else
- {
- free(buf);
- return NULL;
- }
-}
-
-JNIEXPORT void JNICALL
-JNI_FN(MuPDFCore_saveInternal)(JNIEnv * env, jobject thiz)
-{
- globals *glo = get_globals(env, thiz);
- fz_context *ctx = glo->ctx;
-
- if (glo->doc && glo->current_path)
- {
- char *tmp;
- fz_write_options opts;
- opts.do_ascii = 1;
- opts.do_expand = 0;
- opts.do_garbage = 1;
- opts.do_linear = 0;
-
- tmp = tmp_path(glo->current_path);
- if (tmp)
- {
- int written;
-
- fz_var(written);
- fz_try(ctx)
- {
- fz_write_document(glo->doc, tmp, &opts);
- written = 1;
- }
- fz_catch(ctx)
- {
- written = 0;
- }
-
- if (written)
- {
- close_doc(glo);
- rename(tmp, glo->current_path);
- }
-
- free(tmp);
- }
- }
-}
-
-JNIEXPORT void JNICALL
-JNI_FN(MuPDFCore_dumpMemoryInternal)(JNIEnv * env, jobject thiz)
-{
- globals *glo = get_globals(env, thiz);
- fz_context *ctx = glo->ctx;
-
-#ifdef MEMENTO
- LOGE("dumpMemoryInternal start");
- Memento_listNewBlocks();
- Memento_stats();
- LOGE("dumpMemoryInternal end");
-#endif
-}