Mercurial > hgrepos > Python2 > PyMuPDF
view mupdf-source/platform/java/jni/context.c @ 29:f76e6575dca9 v1.26.4+1
+++++ v1.26.4+1
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Fri, 19 Sep 2025 19:59:23 +0200 |
| parents | b50eed0cc0ef |
| children |
line wrap: on
line source
// Copyright (C) 2004-2025 Artifex Software, Inc. // // This file is part of MuPDF. // // MuPDF is free software: you can redistribute it and/or modify it under the // terms of the GNU Affero General Public License as published by the Free // Software Foundation, either version 3 of the License, or (at your option) // any later version. // // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more // details. // // You should have received a copy of the GNU Affero General Public License // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html> // // Alternative licensing terms are available from the licensor. // For commercial licensing, see <https://www.artifex.com/> or contact // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, // CA 94129, USA, for further information. /* Context interface */ /* Put the fz_context in thread-local storage */ #ifdef _WIN32 static CRITICAL_SECTION mutexes[FZ_LOCK_MAX]; #else static pthread_mutex_t mutexes[FZ_LOCK_MAX]; #endif static void lock(void *user, int lock) { #ifdef _WIN32 EnterCriticalSection(&mutexes[lock]); #else (void)pthread_mutex_lock(&mutexes[lock]); #endif } static void unlock(void *user, int lock) { #ifdef _WIN32 LeaveCriticalSection(&mutexes[lock]); #else (void)pthread_mutex_unlock(&mutexes[lock]); #endif } static const fz_locks_context locks = { NULL, /* user */ lock, unlock }; static void fin_base_context(JNIEnv *env) { int i; fz_drop_context(base_context); base_context = NULL; for (i = 0; i < FZ_LOCK_MAX; i++) #ifdef _WIN32 DeleteCriticalSection(&mutexes[i]); #else (void)pthread_mutex_destroy(&mutexes[i]); #endif } #ifndef _WIN32 static void drop_tls_context(void *arg) { fz_context *ctx = (fz_context *)arg; fz_drop_context(ctx); } #endif static void log_callback(void *user, const char *message) { jboolean detach = JNI_FALSE; JNIEnv *env = NULL; jobject jcallback; jstring jmessage; jobject jlock; jmethodID mid; env = jni_attach_thread(&detach); if (env == NULL) return; if (user != NULL) mid = mid_Context_Log_error; else mid = mid_Context_Log_warning; jcallback = (*env)->GetStaticObjectField(env, cls_Context, fid_Context_log); if (jcallback) { jlock = (*env)->GetStaticObjectField(env, cls_Context, fid_Context_lock); (*env)->MonitorEnter(env, jlock); jmessage = (*env)->NewStringUTF(env, message); (*env)->CallVoidMethod(env, jcallback, mid, jmessage); (*env)->DeleteLocalRef(env, jmessage); (*env)->MonitorExit(env, jlock); (*env)->DeleteLocalRef(env, jcallback); (*env)->DeleteLocalRef(env, jlock); } jni_detach_thread(detach); } static int init_base_context(JNIEnv *env) { int i; #ifdef FZ_JAVA_STORE_SIZE size_t fz_store_size = FZ_JAVA_STORE_SIZE; #else size_t fz_store_size = FZ_STORE_DEFAULT; #endif char *env_fz_store_size; #ifdef _WIN32 /* No destructor on windows. We will leak contexts. * There is no easy way around this, but this page: * http://stackoverflow.com/questions/3241732/is-there-anyway-to-dynamically-free-thread-local-storage-in-the-win32-apis/3245082#3245082 * suggests a workaround that we can implement if we * need to. */ context_key = TlsAlloc(); if (context_key == TLS_OUT_OF_INDEXES) { LOGE("cannot get thread local storage for storing base context"); return -1; } #else int ret = pthread_key_create(&context_key, drop_tls_context); if (ret < 0) { LOGE("cannot get thread local storage for storing base context"); return -1; } #endif for (i = 0; i < FZ_LOCK_MAX; i++) #ifdef _WIN32 InitializeCriticalSection(&mutexes[i]); #else (void)pthread_mutex_init(&mutexes[i], NULL); #endif env_fz_store_size = getenv("FZ_JAVA_STORE_SIZE"); if (env_fz_store_size) fz_store_size = fz_atoz(env_fz_store_size); base_context = fz_new_context(NULL, &locks, fz_store_size); if (!base_context) { LOGE("cannot create base context"); fin_base_context(env); return -1; } fz_set_error_callback(base_context, log_callback, (void *) 1); fz_set_warning_callback(base_context, log_callback, (void *) 0); fz_try(base_context) fz_register_document_handlers(base_context); fz_catch(base_context) { fz_report_error(base_context); LOGE("cannot register document handlers"); fin_base_context(env); return -1; } #ifdef HAVE_ANDROID fz_install_load_system_font_funcs(base_context, load_droid_font, load_droid_cjk_font, load_droid_fallback_font); #endif return 0; } static fz_context *get_context(JNIEnv *env) { fz_context *ctx = (fz_context *) #ifdef _WIN32 TlsGetValue(context_key); if (ctx == NULL && GetLastError() != ERROR_SUCCESS) jni_throw_run(env, "cannot get context"); #else pthread_getspecific(context_key); #endif if (ctx) return ctx; ctx = fz_clone_context(base_context); if (!ctx) jni_throw_oom(env, "failed to clone fz_context"); #ifdef _WIN32 if (TlsSetValue(context_key, ctx) == 0) jni_throw_run(env, "cannot store context"); #else if (pthread_setspecific(context_key, ctx) != 0) jni_throw_run(env, "cannot store context"); #endif return ctx; } JNIEXPORT jint JNICALL FUN(Context_initNative)(JNIEnv *env, jclass cls) { if (!check_enums()) return -1; /* Must init the context before find_finds, because the act of * finding the fids can cause classes to load. This causes * statics to be setup, which can in turn call JNI code, which * requires the context. (For example see ColorSpace) */ if (init_base_context(env) < 0) return -1; if (find_fids(env) < 0) { fin_base_context(env); return -1; } return 0; } JNIEXPORT void JNICALL FUN(Context_emptyStore)(JNIEnv *env, jclass cls) { fz_context *ctx = get_context(env); if (!ctx) return; fz_empty_store(ctx); } JNIEXPORT void JNICALL FUN(Context_enableICC)(JNIEnv *env, jclass cls) { fz_context *ctx = get_context(env); if (!ctx) return; fz_enable_icc(ctx); } JNIEXPORT void JNICALL FUN(Context_disableICC)(JNIEnv *env, jclass cls) { fz_context *ctx = get_context(env); if (!ctx) return; fz_disable_icc(ctx); } JNIEXPORT void JNICALL FUN(Context_setAntiAliasLevel)(JNIEnv *env, jclass cls, jint level) { fz_context *ctx = get_context(env); if (!ctx) return; fz_set_aa_level(ctx, level); } JNIEXPORT jobject JNICALL FUN(Context_getVersion)(JNIEnv *env, jclass cls) { fz_context *ctx = get_context(env); jobject jversion = NULL; jobject jvs = NULL; if (!ctx) return NULL; jvs = (*env)->NewStringUTF(env, FZ_VERSION); if (!jvs || (*env)->ExceptionCheck(env)) return NULL; jversion = (*env)->NewObject(env, cls_Context_Version, mid_Context_Version_init); if (!jversion || (*env)->ExceptionCheck(env)) return NULL; (*env)->SetIntField(env, jversion, fid_Context_Version_major, FZ_VERSION_MAJOR); (*env)->SetIntField(env, jversion, fid_Context_Version_minor, FZ_VERSION_MINOR); (*env)->SetIntField(env, jversion, fid_Context_Version_patch, FZ_VERSION_PATCH); (*env)->SetObjectField(env, jversion, fid_Context_Version_version, jvs); return jversion; } JNIEXPORT void JNICALL FUN(Context_setUserCSS)(JNIEnv *env, jclass cls, jstring jcss) { fz_context *ctx = get_context(env); const char *css = NULL; if (jcss) css = (*env)->GetStringUTFChars(env, jcss, NULL); fz_try(ctx) fz_set_user_css(ctx, css); fz_always(ctx) if (jcss) (*env)->ReleaseStringUTFChars(env, jcss, css); fz_catch(ctx) jni_rethrow_void(env, ctx); } JNIEXPORT void JNICALL FUN(Context_useDocumentCSS)(JNIEnv *env, jclass cls, jboolean state) { fz_context *ctx = get_context(env); fz_try(ctx) fz_set_use_document_css(ctx, state); fz_catch(ctx) jni_rethrow_void(env, ctx); } JNIEXPORT jboolean JNICALL FUN(Context_shrinkStore)(JNIEnv *env, jclass cls, jint percent) { fz_context *ctx = get_context(env); int success = 0; if (!ctx) return JNI_FALSE; if (percent < 0) jni_throw_arg(env, "percent must not be negative"); if (percent > 100) jni_throw_arg(env, "percent must not be more than 100"); fz_try(ctx) success = fz_shrink_store(ctx, percent); fz_catch(ctx) jni_rethrow(env, ctx); return success != 0; }
