diff options
-rw-r--r-- | android/jni/mupdf.c | 478 | ||||
-rw-r--r-- | android/src/com/artifex/mupdf/MuPDFCore.java | 57 |
2 files changed, 307 insertions, 228 deletions
diff --git a/android/jni/mupdf.c b/android/jni/mupdf.c index a89b773c..c0a8d791 100644 --- a/android/jni/mupdf.c +++ b/android/jni/mupdf.c @@ -49,20 +49,52 @@ typedef struct fz_display_list *annot_list; } page_cache; +typedef struct globals_s globals; -/* Globals */ -fz_colorspace *colorspace; -fz_document *doc; -int resolution = 160; -fz_context *ctx; -fz_bbox *hit_bbox = NULL; -int current; -char *current_path = NULL; +struct globals_s +{ + fz_colorspace *colorspace; + fz_document *doc; + int resolution; + fz_context *ctx; + fz_bbox *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. + fz_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; +}; -page_cache pages[NUM_CACHE] = {{0}}; +static jfieldID global_fid; -static void drop_page_cache(page_cache *pc) +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_free_display_list(ctx, pc->page_list); pc->page_list = NULL; @@ -74,111 +106,91 @@ static void drop_page_cache(page_cache *pc) pc->hq_page = NULL; } -static void clear_hq_pages() +static void clear_hq_pages(globals *glo) { int i; + fz_document *doc = glo->doc; for (i = 0; i < NUM_CACHE; i++) { - fz_free_page(doc, pages[i].hq_page); - pages[i].hq_page = NULL; + fz_free_page(doc, glo->pages[i].hq_page); + glo->pages[i].hq_page = NULL; } } -static void dump_annotation_display_lists() +static void dump_annotation_display_lists(globals *glo) { + fz_context *ctx = glo->ctx; int i; for (i = 0; i < NUM_CACHE; i++) { - fz_free_display_list(ctx, pages[i].annot_list); - pages[i].annot_list = NULL; + fz_free_display_list(ctx, glo->pages[i].annot_list); + glo->pages[i].annot_list = NULL; } } -static alerts_initialised = 0; -// 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. -static pthread_mutex_t fin_lock; -static pthread_mutex_t fin_lock2; -// alert_lock is the main lock guarding the variables directly below. -static pthread_mutex_t alert_lock; -// Flag indicating if the alert system is active. When not active, both -// show_alert and waitForAlertInternal return immediately. -static int alerts_active; -// Pointer to the alert struct passed in by show_alert, and valid while -// show_alert is blocked. -static fz_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. -static int alert_request; -static int alert_reply; -static pthread_cond_t alert_request_cond; -static pthread_cond_t alert_reply_cond; - -static void show_alert(fz_alert_event *alert) +static void show_alert(globals *glo, fz_alert_event *alert) { - pthread_mutex_lock(&fin_lock2); - pthread_mutex_lock(&alert_lock); + pthread_mutex_lock(&glo->fin_lock2); + pthread_mutex_lock(&glo->alert_lock); LOGT("Enter show_alert: %s", alert->title); alert->button_pressed = 0; - if (alerts_active) + if (glo->alerts_active) { - current_alert = alert; - alert_request = 1; - pthread_cond_signal(&alert_request_cond); - - while (alerts_active && !alert_reply) - pthread_cond_wait(&alert_reply_cond, &alert_lock); - alert_reply = 0; - current_alert = NULL; + 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(&alert_lock); - pthread_mutex_unlock(&fin_lock2); + pthread_mutex_unlock(&glo->alert_lock); + pthread_mutex_unlock(&glo->fin_lock2); } static void event_cb(fz_doc_event *event, void *data) { + globals *glo = (globals *)data; + switch (event->type) { case FZ_DOCUMENT_EVENT_ALERT: - show_alert(fz_access_alert_event(event)); + show_alert(glo, fz_access_alert_event(event)); break; } } -static void alerts_init() +static void alerts_init(globals *glo) { - fz_interactive *idoc = fz_interact(doc); + fz_interactive *idoc = fz_interact(glo->doc); - if (!idoc || alerts_initialised) + if (!idoc || glo->alerts_initialised) return; - alerts_active = 0; - alert_request = 0; - alert_reply = 0; - pthread_mutex_init(&fin_lock, NULL); - pthread_mutex_init(&fin_lock2, NULL); - pthread_mutex_init(&alert_lock, NULL); - pthread_cond_init(&alert_request_cond, NULL); - pthread_cond_init(&alert_reply_cond, NULL); + 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); - fz_set_doc_event_callback(idoc, event_cb, NULL); + fz_set_doc_event_callback(idoc, event_cb, glo); LOGT("alert_init"); - alerts_initialised = 1; + glo->alerts_initialised = 1; } -static void alerts_fin() +static void alerts_fin(globals *glo) { - fz_interactive *idoc = fz_interact(doc); - if (!alerts_initialised) + fz_interactive *idoc = fz_interact(glo->doc); + if (!glo->alerts_initialised) return; LOGT("Enter alerts_fin"); @@ -186,90 +198,111 @@ static void alerts_fin() fz_set_doc_event_callback(idoc, NULL, NULL); // Set alerts_active false and wake up show_alert and waitForAlertInternal, - pthread_mutex_lock(&alert_lock); - current_alert = NULL; - alerts_active = 0; - pthread_cond_signal(&alert_request_cond); - pthread_cond_signal(&alert_reply_cond); - pthread_mutex_unlock(&alert_lock); + 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(&fin_lock); - pthread_mutex_unlock(&fin_lock); - pthread_mutex_lock(&fin_lock2); - pthread_mutex_unlock(&fin_lock2); - - pthread_cond_destroy(&alert_reply_cond); - pthread_cond_destroy(&alert_request_cond); - pthread_mutex_destroy(&alert_lock); - pthread_mutex_destroy(&fin_lock2); - pthread_mutex_destroy(&fin_lock); + 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"); - alerts_initialised = 0; + glo->alerts_initialised = 0; } -JNIEXPORT int JNICALL +static globals *get_globals(JNIEnv *env, jobject thiz) +{ + return (globals *)(void *)((*env)->GetLongField(env, thiz, global_fid)); +} + +JNIEXPORT jlong JNICALL Java_com_artifex_mupdf_MuPDFCore_openFile(JNIEnv * env, jobject thiz, jstring jfilename) { const char *filename; - int result = 0; + 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. */ - ctx = fz_new_context(NULL, NULL, 128 << 20); + glo->ctx = ctx = fz_new_context(NULL, NULL, 128 << 20); if (!ctx) { LOGE("Failed to initialise context"); + free(glo); return 0; } - doc = NULL; + glo->doc = NULL; fz_try(ctx) { - colorspace = fz_device_rgb; + glo->colorspace = fz_device_rgb; LOGE("Opening document..."); fz_try(ctx) { - current_path = fz_strdup(ctx, (char *)filename); - doc = fz_open_document(ctx, (char *)filename); - alerts_init(); + 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, "Cannot open document: '%s'\n", filename); } LOGE("Done!"); - result = 1; } fz_catch(ctx) { LOGE("Failed: %s", ctx->error->message); - fz_close_document(doc); - doc = NULL; + fz_close_document(glo->doc); + glo->doc = NULL; fz_free_context(ctx); - ctx = NULL; + glo->ctx = NULL; + free(glo); + glo = NULL; } (*env)->ReleaseStringUTFChars(env, jfilename, filename); - return result; + return (jlong)(void *)glo; } JNIEXPORT int JNICALL Java_com_artifex_mupdf_MuPDFCore_countPagesInternal(JNIEnv *env, jobject thiz) { - return fz_count_pages(doc); + globals *glo = get_globals(env, thiz); + + return fz_count_pages(glo->doc); } JNIEXPORT void JNICALL @@ -282,17 +315,19 @@ Java_com_artifex_mupdf_MuPDFCore_gotoPageInternal(JNIEnv *env, jobject thiz, int fz_matrix ctm; fz_bbox bbox; page_cache *pc; + globals *glo = get_globals(env, thiz); + fz_context *ctx = glo->ctx; for (i = 0; i < NUM_CACHE; i++) { - if (pages[i].page != NULL && pages[i].number == page) + if (glo->pages[i].page != NULL && glo->pages[i].number == page) { /* The page is already cached */ - current = i; + glo->current = i; return; } - if (pages[i].page == NULL) + if (glo->pages[i].page == NULL) { /* cache record unused, and so a good one to use */ furthest = i; @@ -300,7 +335,7 @@ Java_com_artifex_mupdf_MuPDFCore_gotoPageInternal(JNIEnv *env, jobject thiz, int } else { - int dist = abs(pages[i].number - page); + int dist = abs(glo->pages[i].number - page); /* Further away - less likely to be needed again */ if (dist > furthest_dist) @@ -311,10 +346,10 @@ Java_com_artifex_mupdf_MuPDFCore_gotoPageInternal(JNIEnv *env, jobject thiz, int } } - current = furthest; - pc = &pages[current]; + glo->current = furthest; + pc = &glo->pages[glo->current]; - drop_page_cache(pc); + drop_page_cache(glo, pc); /* In the event of an error, ensure we give a non-empty page */ pc->width = 100; @@ -325,9 +360,9 @@ Java_com_artifex_mupdf_MuPDFCore_gotoPageInternal(JNIEnv *env, jobject thiz, int fz_try(ctx) { LOGI("Load page %d", pc->number); - pc->page = fz_load_page(doc, pc->number); - zoom = resolution / 72; - pc->media_box = fz_bound_page(doc, pc->page); + pc->page = fz_load_page(glo->doc, pc->number); + zoom = glo->resolution / 72; + pc->media_box = fz_bound_page(glo->doc, pc->page); ctm = fz_scale(zoom, zoom); bbox = fz_round_rect(fz_transform_rect(ctm, pc->media_box)); pc->width = bbox.x1-bbox.x0; @@ -342,15 +377,17 @@ Java_com_artifex_mupdf_MuPDFCore_gotoPageInternal(JNIEnv *env, jobject thiz, int JNIEXPORT float JNICALL Java_com_artifex_mupdf_MuPDFCore_getPageWidth(JNIEnv *env, jobject thiz) { - LOGE("PageWidth=%g", pages[current].width); - return pages[current].width; + globals *glo = get_globals(env, thiz); + LOGE("PageWidth=%d", glo->pages[glo->current].width); + return glo->pages[glo->current].width; } JNIEXPORT float JNICALL Java_com_artifex_mupdf_MuPDFCore_getPageHeight(JNIEnv *env, jobject thiz) { - LOGE("PageHeight=%g", pages[current].height); - return pages[current].height; + globals *glo = get_globals(env, thiz); + LOGE("PageHeight=%d", glo->pages[glo->current].height); + return glo->pages[glo->current].height; } JNIEXPORT jboolean JNICALL @@ -373,7 +410,10 @@ Java_com_artifex_mupdf_MuPDFCore_drawPage(JNIEnv *env, jobject thiz, jobject bit fz_pixmap *pix = NULL; float xscale, yscale; fz_bbox rect; - page_cache *pc = &pages[current]; + 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); if (pc->page == NULL) @@ -421,7 +461,7 @@ Java_com_artifex_mupdf_MuPDFCore_drawPage(JNIEnv *env, jobject thiz, jobject bit } else { // There is only ever one hq patch, so we need // cache only one page object for the sake of hq - clear_hq_pages(); + clear_hq_pages(glo); pc->hq_page = fz_load_page(doc, pc->number); } } @@ -450,7 +490,7 @@ Java_com_artifex_mupdf_MuPDFCore_drawPage(JNIEnv *env, jobject thiz, jobject bit rect.y0 = patchY; rect.x1 = patchX + patchW; rect.y1 = patchY + patchH; - pix = fz_new_pixmap_with_bbox_and_data(ctx, colorspace, rect, pixels); + pix = fz_new_pixmap_with_bbox_and_data(ctx, glo->colorspace, rect, pixels); if (pc->page_list == NULL && pc->annot_list == NULL) { fz_clear_pixmap_with_value(ctx, pix, 0xd0); @@ -458,7 +498,7 @@ Java_com_artifex_mupdf_MuPDFCore_drawPage(JNIEnv *env, jobject thiz, jobject bit } fz_clear_pixmap_with_value(ctx, pix, 0xff); - zoom = resolution / 72; + zoom = glo->resolution / 72; ctm = fz_scale(zoom, zoom); bbox = fz_round_rect(fz_transform_rect(ctm, pc->media_box)); /* Now, adjust ctm so that it would give the correct page width @@ -533,12 +573,15 @@ Java_com_artifex_mupdf_MuPDFCore_updatePageInternal(JNIEnv *env, jobject thiz, j 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; for (i = 0; i < NUM_CACHE; i++) { - if (pages[i].page != NULL && pages[i].number == page) + if (glo->pages[i].page != NULL && glo->pages[i].number == page) { - pc = &pages[i]; + pc = &glo->pages[i]; break; } } @@ -608,9 +651,9 @@ Java_com_artifex_mupdf_MuPDFCore_updatePageInternal(JNIEnv *env, jobject thiz, j rect.y0 = patchY; rect.x1 = patchX + patchW; rect.y1 = patchY + patchH; - pix = fz_new_pixmap_with_bbox_and_data(ctx, colorspace, rect, pixels); + pix = fz_new_pixmap_with_bbox_and_data(ctx, glo->colorspace, rect, pixels); - zoom = resolution / 72; + zoom = glo->resolution / 72; ctm = fz_scale(zoom, zoom); bbox = fz_round_rect(fz_transform_rect(ctm, pc->media_box)); /* Now, adjust ctm so that it would give the correct page width @@ -787,7 +830,9 @@ fillInOutlineItems(JNIEnv * env, jclass olClass, jmethodID ctor, jobjectArray ar JNIEXPORT jboolean JNICALL Java_com_artifex_mupdf_MuPDFCore_needsPasswordInternal(JNIEnv * env, jobject thiz) { - return fz_needs_password(doc) ? JNI_TRUE : JNI_FALSE; + globals *glo = get_globals(env, thiz); + + return fz_needs_password(glo->doc) ? JNI_TRUE : JNI_FALSE; } JNIEXPORT jboolean JNICALL @@ -795,11 +840,13 @@ Java_com_artifex_mupdf_MuPDFCore_authenticatePasswordInternal(JNIEnv *env, jobje { 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(doc, (char *)pw); + result = fz_authenticate_password(glo->doc, (char *)pw); (*env)->ReleaseStringUTFChars(env, password, pw); return result; } @@ -807,7 +854,9 @@ Java_com_artifex_mupdf_MuPDFCore_authenticatePasswordInternal(JNIEnv *env, jobje JNIEXPORT jboolean JNICALL Java_com_artifex_mupdf_MuPDFCore_hasOutlineInternal(JNIEnv * env, jobject thiz) { - fz_outline *outline = fz_load_outline(doc); + globals *glo = get_globals(env, thiz); + fz_outline *outline = fz_load_outline(glo->doc); + return (outline == NULL) ? JNI_FALSE : JNI_TRUE; } @@ -820,13 +869,14 @@ Java_com_artifex_mupdf_MuPDFCore_getOutlineInternal(JNIEnv * env, jobject thiz) jobject ol; fz_outline *outline; int nItems; + globals *glo = get_globals(env, thiz); olClass = (*env)->FindClass(env, "com/artifex/mupdf/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(doc); + outline = fz_load_outline(glo->doc); nItems = countOutlineItems(outline); arr = (*env)->NewObjectArray(env, @@ -857,7 +907,10 @@ Java_com_artifex_mupdf_MuPDFCore_searchPage(JNIEnv * env, jobject thiz, jstring int i, n; int hit_count = 0; const char *str; - page_cache *pc = &pages[current]; + 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; @@ -874,10 +927,10 @@ Java_com_artifex_mupdf_MuPDFCore_searchPage(JNIEnv * env, jobject thiz, jstring { fz_rect rect; - if (hit_bbox == NULL) - hit_bbox = fz_malloc_array(ctx, MAX_SEARCH_HITS, sizeof(*hit_bbox)); + if (glo->hit_bbox == NULL) + glo->hit_bbox = fz_malloc_array(ctx, MAX_SEARCH_HITS, sizeof(*glo->hit_bbox)); - zoom = resolution / 72; + zoom = glo->resolution / 72; ctm = fz_scale(zoom, zoom); rect = fz_transform_rect(ctm, pc->media_box); sheet = fz_new_text_sheet(ctx); @@ -896,7 +949,7 @@ Java_com_artifex_mupdf_MuPDFCore_searchPage(JNIEnv * env, jobject thiz, jstring rr = fz_union_bbox(rr, bboxcharat(text, pos + i)); if (!fz_is_empty_bbox(rr) && hit_count < MAX_SEARCH_HITS) - hit_bbox[hit_count++] = rr; + glo->hit_bbox[hit_count++] = rr; } } fz_always(ctx) @@ -927,10 +980,10 @@ Java_com_artifex_mupdf_MuPDFCore_searchPage(JNIEnv * env, jobject thiz, jstring for (i = 0; i < hit_count; i++) { rect = (*env)->NewObject(env, rectClass, ctor, - (float) (hit_bbox[i].x0), - (float) (hit_bbox[i].y0), - (float) (hit_bbox[i].x1), - (float) (hit_bbox[i].y1)); + (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); @@ -940,29 +993,32 @@ Java_com_artifex_mupdf_MuPDFCore_searchPage(JNIEnv * env, jobject thiz, jstring return arr; } -static void close_doc() +static void close_doc(globals *glo) { int i; - fz_free(ctx, hit_bbox); - hit_bbox = NULL; + fz_free(glo->ctx, glo->hit_bbox); + glo->hit_bbox = NULL; for (i = 0; i < NUM_CACHE; i++) - drop_page_cache(&pages[i]); + drop_page_cache(glo, &glo->pages[i]); - alerts_fin(); + alerts_fin(glo); - fz_close_document(doc); - doc = NULL; + fz_close_document(glo->doc); + glo->doc = NULL; } JNIEXPORT void JNICALL Java_com_artifex_mupdf_MuPDFCore_destroying(JNIEnv * env, jobject thiz) { + globals *glo = get_globals(env, thiz); + LOGI("Destroying"); - close_doc(); - fz_free(ctx, current_path); - current_path = NULL; + close_doc(glo); + fz_free(glo->ctx, glo->current_path); + glo->current_path = NULL; + free(glo); #ifdef NDK_PROFILER // Apparently we should really be writing to whatever path we get @@ -987,6 +1043,7 @@ Java_com_artifex_mupdf_MuPDFCore_getPageLinksInternal(JNIEnv * env, jobject thiz fz_link *link; int count; page_cache *pc; + globals *glo = get_globals(env, thiz); linkInfoClass = (*env)->FindClass(env, "com/artifex/mupdf/LinkInfo"); if (linkInfoClass == NULL) return NULL; @@ -994,14 +1051,14 @@ Java_com_artifex_mupdf_MuPDFCore_getPageLinksInternal(JNIEnv * env, jobject thiz if (ctor == NULL) return NULL; Java_com_artifex_mupdf_MuPDFCore_gotoPageInternal(env, thiz, pageNumber); - pc = &pages[current]; + pc = &glo->pages[glo->current]; if (pc->page == NULL || pc->number != pageNumber) return NULL; - zoom = resolution / 72; + zoom = glo->resolution / 72; ctm = fz_scale(zoom, zoom); - list = fz_load_links(doc, pc->page); + list = fz_load_links(glo->doc, pc->page); count = 0; for (link = list; link; link = link->next) { @@ -1046,6 +1103,7 @@ Java_com_artifex_mupdf_MuPDFCore_getWidgetAreasInternal(JNIEnv * env, jobject th 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; @@ -1053,15 +1111,15 @@ Java_com_artifex_mupdf_MuPDFCore_getWidgetAreasInternal(JNIEnv * env, jobject th if (ctor == NULL) return NULL; Java_com_artifex_mupdf_MuPDFCore_gotoPageInternal(env, thiz, pageNumber); - pc = &pages[current]; + pc = &glo->pages[glo->current]; if (pc->number != pageNumber || pc->page == NULL) return NULL; - idoc = fz_interact(doc); + idoc = fz_interact(glo->doc); if (idoc == NULL) return NULL; - zoom = resolution / 72; + zoom = glo->resolution / 72; ctm = fz_scale(zoom, zoom); count = 0; @@ -1096,9 +1154,10 @@ Java_com_artifex_mupdf_MuPDFCore_getPageLink(JNIEnv * env, jobject thiz, int pag fz_link *link; fz_point p; page_cache *pc; + globals *glo = get_globals(env, thiz); Java_com_artifex_mupdf_MuPDFCore_gotoPageInternal(env, thiz, pageNumber); - pc = &pages[current]; + pc = &glo->pages[glo->current]; if (pc->number != pageNumber || pc->page == NULL) return -1; @@ -1108,13 +1167,13 @@ Java_com_artifex_mupdf_MuPDFCore_getPageLink(JNIEnv * env, jobject thiz, int pag /* 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; + zoom = glo->resolution / 72; ctm = fz_scale(zoom, zoom); ctm = fz_invert_matrix(ctm); p = fz_transform_point(ctm, p); - for (link = fz_load_links(doc, pc->page); link; link = link->next) + for (link = fz_load_links(glo->doc, pc->page); link; link = link->next) { if (p.x >= link->rect.x0 && p.x <= link->rect.x1) if (p.y >= link->rect.y0 && p.y <= link->rect.y1) @@ -1137,8 +1196,10 @@ Java_com_artifex_mupdf_MuPDFCore_getPageLink(JNIEnv * env, jobject thiz, int pag JNIEXPORT int JNICALL Java_com_artifex_mupdf_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; - fz_interactive *idoc = fz_interact(doc); + fz_interactive *idoc = fz_interact(glo->doc); float zoom; fz_point p; fz_ui_event event; @@ -1149,7 +1210,7 @@ Java_com_artifex_mupdf_MuPDFCore_passClickEventInternal(JNIEnv * env, jobject th return 0; Java_com_artifex_mupdf_MuPDFCore_gotoPageInternal(env, thiz, pageNumber); - pc = &pages[current]; + pc = &glo->pages[glo->current]; if (pc->number != pageNumber || pc->page == NULL) return 0; @@ -1159,7 +1220,7 @@ Java_com_artifex_mupdf_MuPDFCore_passClickEventInternal(JNIEnv * env, jobject th /* 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; + zoom = glo->resolution / 72; ctm = fz_scale(zoom, zoom); ctm = fz_invert_matrix(ctm); @@ -1174,7 +1235,7 @@ Java_com_artifex_mupdf_MuPDFCore_passClickEventInternal(JNIEnv * env, jobject th event.event.pointer.ptype = FZ_POINTER_UP; changed |= fz_pass_event(idoc, pc->page, &event); if (changed) { - dump_annotation_display_lists(); + dump_annotation_display_lists(glo); } } fz_catch(ctx) @@ -1189,10 +1250,12 @@ JNIEXPORT jstring JNICALL Java_com_artifex_mupdf_MuPDFCore_getFocusedWidgetTextInternal(JNIEnv * env, jobject thiz) { char *text = ""; + globals *glo = get_globals(env, thiz); + fz_context *ctx = glo->ctx; fz_try(ctx) { - fz_interactive *idoc = fz_interact(doc); + fz_interactive *idoc = fz_interact(glo->doc); if (idoc) { @@ -1215,6 +1278,8 @@ Java_com_artifex_mupdf_MuPDFCore_setFocusedWidgetTextInternal(JNIEnv * env, jobj { 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) @@ -1225,7 +1290,7 @@ Java_com_artifex_mupdf_MuPDFCore_setFocusedWidgetTextInternal(JNIEnv * env, jobj fz_try(ctx) { - fz_interactive *idoc = fz_interact(doc); + fz_interactive *idoc = fz_interact(glo->doc); if (idoc) { @@ -1234,7 +1299,7 @@ Java_com_artifex_mupdf_MuPDFCore_setFocusedWidgetTextInternal(JNIEnv * env, jobj if (focus) { result = fz_text_widget_set_text(idoc, focus, (char *)text); - dump_annotation_display_lists(); + dump_annotation_display_lists(glo); } } } @@ -1251,7 +1316,8 @@ Java_com_artifex_mupdf_MuPDFCore_setFocusedWidgetTextInternal(JNIEnv * env, jobj JNIEXPORT int JNICALL Java_com_artifex_mupdf_MuPDFCore_getFocusedWidgetTypeInternal(JNIEnv * env, jobject thiz) { - fz_interactive *idoc = fz_interact(doc); + globals *glo = get_globals(env, thiz); + fz_interactive *idoc = fz_interact(glo->doc); fz_widget *focus; if (idoc == NULL) @@ -1275,6 +1341,7 @@ Java_com_artifex_mupdf_MuPDFCore_getFocusedWidgetTypeInternal(JNIEnv * env, jobj JNIEXPORT jobject JNICALL Java_com_artifex_mupdf_MuPDFCore_waitForAlertInternal(JNIEnv * env, jobject thiz) { + globals *glo = get_globals(env, thiz); jclass alertClass; jmethodID ctor; jstring title; @@ -1283,20 +1350,20 @@ Java_com_artifex_mupdf_MuPDFCore_waitForAlertInternal(JNIEnv * env, jobject thiz fz_alert_event alert; LOGT("Enter waitForAlert"); - pthread_mutex_lock(&fin_lock); - pthread_mutex_lock(&alert_lock); + pthread_mutex_lock(&glo->fin_lock); + pthread_mutex_lock(&glo->alert_lock); - while (alerts_active && !alert_request) - pthread_cond_wait(&alert_request_cond, &alert_lock); - alert_request = 0; + while (glo->alerts_active && !glo->alert_request) + pthread_cond_wait(&glo->alert_request_cond, &glo->alert_lock); + glo->alert_request = 0; - alert_present = (alerts_active && current_alert); + alert_present = (glo->alerts_active && glo->current_alert); if (alert_present) - alert = *current_alert; + alert = *glo->current_alert; - pthread_mutex_unlock(&alert_lock); - pthread_mutex_unlock(&fin_lock); + pthread_mutex_unlock(&glo->alert_lock); + pthread_mutex_unlock(&glo->fin_lock); LOGT("Exit waitForAlert %d", alert_present); if (!alert_present) @@ -1324,6 +1391,7 @@ Java_com_artifex_mupdf_MuPDFCore_waitForAlertInternal(JNIEnv * env, jobject thiz JNIEXPORT void JNICALL Java_com_artifex_mupdf_MuPDFCore_replyToAlertInternal(JNIEnv * env, jobject thiz, jobject alert) { + globals *glo = get_globals(env, thiz); jclass alertClass; jfieldID field; int button_pressed; @@ -1339,62 +1407,67 @@ Java_com_artifex_mupdf_MuPDFCore_replyToAlertInternal(JNIEnv * env, jobject thiz button_pressed = (*env)->GetIntField(env, alert, field); LOGT("Enter replyToAlert"); - pthread_mutex_lock(&alert_lock); + pthread_mutex_lock(&glo->alert_lock); - if (alerts_active && current_alert) + if (glo->alerts_active && glo->current_alert) { // Fill in button_pressed and signal reply received. - current_alert->button_pressed = button_pressed; - alert_reply = 1; - pthread_cond_signal(&alert_reply_cond); + glo->current_alert->button_pressed = button_pressed; + glo->alert_reply = 1; + pthread_cond_signal(&glo->alert_reply_cond); } - pthread_mutex_unlock(&alert_lock); + pthread_mutex_unlock(&glo->alert_lock); LOGT("Exit replyToAlert"); } JNIEXPORT void JNICALL Java_com_artifex_mupdf_MuPDFCore_startAlertsInternal(JNIEnv * env, jobject thiz) { - if (!alerts_initialised) + globals *glo = get_globals(env, thiz); + + if (!glo->alerts_initialised) return; LOGT("Enter startAlerts"); - pthread_mutex_lock(&alert_lock); + pthread_mutex_lock(&glo->alert_lock); - alert_reply = 0; - alert_request = 0; - alerts_active = 1; - current_alert = NULL; + glo->alert_reply = 0; + glo->alert_request = 0; + glo->alerts_active = 1; + glo->current_alert = NULL; - pthread_mutex_unlock(&alert_lock); + pthread_mutex_unlock(&glo->alert_lock); LOGT("Exit startAlerts"); } JNIEXPORT void JNICALL Java_com_artifex_mupdf_MuPDFCore_stopAlertsInternal(JNIEnv * env, jobject thiz) { - if (!alerts_initialised) + globals *glo = get_globals(env, thiz); + + if (!glo->alerts_initialised) return; LOGT("Enter stopAlerts"); - pthread_mutex_lock(&alert_lock); + pthread_mutex_lock(&glo->alert_lock); - alert_reply = 0; - alert_request = 0; - alerts_active = 0; - current_alert = NULL; - pthread_cond_signal(&alert_reply_cond); - pthread_cond_signal(&alert_request_cond); + 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(&alert_lock); + pthread_mutex_unlock(&glo->alert_lock); LOGT("Exit stopAleerts"); } JNIEXPORT jboolean JNICALL Java_com_artifex_mupdf_MuPDFCore_hasChangesInternal(JNIEnv * env, jobject thiz) { - fz_interactive *idoc = fz_interact(doc); + globals *glo = get_globals(env, thiz); + fz_interactive *idoc = fz_interact(glo->doc); return (idoc && fz_has_unsaved_changes(idoc)) ? JNI_TRUE : JNI_FALSE; } @@ -1426,7 +1499,10 @@ static char *tmp_path(char *path) JNIEXPORT void JNICALL Java_com_artifex_mupdf_MuPDFCore_saveInternal(JNIEnv * env, jobject thiz) { - if (doc && current_path) + globals *glo = get_globals(env, thiz); + fz_context *ctx = glo->ctx; + + if (glo->doc && glo->current_path) { char *tmp; fz_write_options opts; @@ -1435,7 +1511,7 @@ Java_com_artifex_mupdf_MuPDFCore_saveInternal(JNIEnv * env, jobject thiz) opts.do_garbage = 1; opts.do_linear = 0; - tmp = tmp_path(current_path); + tmp = tmp_path(glo->current_path); if (tmp) { int written; @@ -1443,7 +1519,7 @@ Java_com_artifex_mupdf_MuPDFCore_saveInternal(JNIEnv * env, jobject thiz) fz_var(written); fz_try(ctx) { - fz_write_document(doc, tmp, &opts); + fz_write_document(glo->doc, tmp, &opts); written = 1; } fz_catch(ctx) @@ -1453,8 +1529,8 @@ Java_com_artifex_mupdf_MuPDFCore_saveInternal(JNIEnv * env, jobject thiz) if (written) { - close_doc(); - rename(tmp, current_path); + close_doc(glo); + rename(tmp, glo->current_path); } free(tmp); diff --git a/android/src/com/artifex/mupdf/MuPDFCore.java b/android/src/com/artifex/mupdf/MuPDFCore.java index 13718508..1f9da3a6 100644 --- a/android/src/com/artifex/mupdf/MuPDFCore.java +++ b/android/src/com/artifex/mupdf/MuPDFCore.java @@ -15,47 +15,49 @@ public class MuPDFCore private int numPages = -1; private float pageWidth; private float pageHeight; + private long globals; /* The native functions */ - private static native int openFile(String filename); - private static native int countPagesInternal(); - private static native void gotoPageInternal(int localActionPageNum); - private static native float getPageWidth(); - private static native float getPageHeight(); - private static native void drawPage(Bitmap bitmap, + private native long openFile(String filename); + private native int countPagesInternal(); + private native void gotoPageInternal(int localActionPageNum); + private native float getPageWidth(); + private native float getPageHeight(); + private native void drawPage(Bitmap bitmap, int pageW, int pageH, int patchX, int patchY, int patchW, int patchH); - private static native void updatePageInternal(Bitmap bitmap, + private native void updatePageInternal(Bitmap bitmap, int page, int pageW, int pageH, int patchX, int patchY, int patchW, int patchH); - 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 int setFocusedWidgetTextInternal(String text); - private static native String getFocusedWidgetTextInternal(); - private static native int getFocusedWidgetTypeInternal(); - 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 MuPDFAlertInternal waitForAlertInternal(); - private static native void replyToAlertInternal(MuPDFAlertInternal alert); - private static native void startAlertsInternal(); - private static native void stopAlertsInternal(); - private static native void destroying(); - private static native boolean hasChangesInternal(); - private static native void saveInternal(); + private native RectF[] searchPage(String text); + private native int getPageLink(int page, float x, float y); + private native int passClickEventInternal(int page, float x, float y); + private native int setFocusedWidgetTextInternal(String text); + private native String getFocusedWidgetTextInternal(); + private native int getFocusedWidgetTypeInternal(); + private native LinkInfo [] getPageLinksInternal(int page); + private native RectF[] getWidgetAreasInternal(int page); + private native OutlineItem [] getOutlineInternal(); + private native boolean hasOutlineInternal(); + private native boolean needsPasswordInternal(); + private native boolean authenticatePasswordInternal(String password); + private native MuPDFAlertInternal waitForAlertInternal(); + private native void replyToAlertInternal(MuPDFAlertInternal alert); + private native void startAlertsInternal(); + private native void stopAlertsInternal(); + private native void destroying(); + private native boolean hasChangesInternal(); + private native void saveInternal(); public static native boolean javascriptSupported(); public MuPDFCore(String filename) throws Exception { - if (openFile(filename) <= 0) + globals = openFile(filename); + if (globals == 0) { throw new Exception("Failed to open "+filename); } @@ -109,6 +111,7 @@ public class MuPDFCore public synchronized void onDestroy() { destroying(); + globals = 0; } public synchronized void drawPage(BitmapHolder h, int page, |