/* * Copyright (C) 2016 The Android Open Source Project * Copyright (C) 2016 Mopria Alliance, Inc. * Copyright (C) 2013 Hewlett-Packard Development Company, L.P. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <jni.h> #include <malloc.h> #include "wprint_mupdf.h" #include "wprint_debug.h" #define TAG "pdf_render" /* Global reference to JVM */ extern JavaVM *_JVM; /* Local data associated with pdf_render_st instances */ typedef struct pdf_render_st { /* Public interface. Must be first. */ pdf_render_ifc_t ifc; /* JNI environment */ JNIEnv *env; /* true if the env was created for this thread */ bool needDetach; /* Reference to associated PdfRender object */ jobject obj; } pdf_render_st_t; static jclass gPdfRenderClass; static jmethodID gPdfRenderOpenDocument, gPdfRenderGetPageSize, gPdfRenderRenderPageStripe; static jclass gSizeDClass; static jmethodID gSizeDGetHeight, gSizeDGetWidth; static int openDocument(pdf_render_ifc_t *obj, const char *fileName) { LOGD("getPageCount %p %s", obj, fileName); if (!gPdfRenderClass) return ERROR; pdf_render_st_t *self = (pdf_render_st_t *) obj; jstring fileNameString = (*self->env)->NewStringUTF(self->env, fileName); int count = (*self->env)->CallIntMethod(self->env, self->obj, gPdfRenderOpenDocument, fileNameString); LOGD("getPageCount %p %s returning %d", obj, fileName, count); return count; } static int getPageAttributes(pdf_render_ifc_t *obj, int page, double *width, double *height) { LOGD("getPageAttributes %p %d", obj, page); if (!gPdfRenderClass) return ERROR; pdf_render_st_t *self = (pdf_render_st_t *) obj; jobject size = (*self->env)->CallObjectMethod(self->env, self->obj, gPdfRenderGetPageSize, page); if (size == NULL) return ERROR; // Extract width/height and return them *width = (double) (*self->env)->CallDoubleMethod(self->env, size, gSizeDGetWidth); *height = (double) (*self->env)->CallDoubleMethod(self->env, size, gSizeDGetHeight); return OK; } static int renderPageStripe(pdf_render_ifc_t *obj, int page, int width, int height, float zoom, char *buffer) { LOGD("renderPageStripe %p %d", obj, page); if (!gPdfRenderClass) return ERROR; pdf_render_st_t *self = (pdf_render_st_t *) obj; int bufferSize = width * height * 3; jobject byteBuffer = (*self->env)->NewDirectByteBuffer(self->env, buffer, bufferSize); if (!(*self->env)->CallBooleanMethod(self->env, self->obj, gPdfRenderRenderPageStripe, page, 0, width, height, (double) zoom, byteBuffer)) { return ERROR; } (*self->env)->DeleteLocalRef(self->env, byteBuffer); return OK; } static void destroy(pdf_render_ifc_t *obj) { LOGD("destroy %p", obj); pdf_render_st_t *self = (pdf_render_st_t *) obj; (*self->env)->DeleteGlobalRef(self->env, self->obj); if (self->needDetach) { (*_JVM)->DetachCurrentThread(_JVM); } free(self); } void pdf_render_init(JNIEnv *env) { LOGD("pdf_render_init"); /* Lock down global class references and look up method IDs */ gPdfRenderClass = (*env)->NewGlobalRef(env, (*env)->FindClass(env, "com/android/bips/jni/PdfRender")); gPdfRenderOpenDocument = (*env)->GetMethodID(env, gPdfRenderClass, "openDocument", "(Ljava/lang/String;)I"); gPdfRenderGetPageSize = (*env)->GetMethodID(env, gPdfRenderClass, "getPageSize", "(I)Lcom/android/bips/jni/SizeD;"); gPdfRenderRenderPageStripe = (*env)->GetMethodID(env, gPdfRenderClass, "renderPageStripe", "(IIIIDLjava/nio/ByteBuffer;)Z"); gSizeDClass = (*env)->NewGlobalRef(env, (*env)->FindClass(env, "com/android/bips/jni/SizeD")); gSizeDGetWidth = (*env)->GetMethodID(env, gSizeDClass, "getWidth", "()D"); gSizeDGetHeight = (*env)->GetMethodID(env, gSizeDClass, "getHeight", "()D"); } void pdf_render_deinit(JNIEnv *env) { LOGD("pdf_render_deinit"); (*env)->DeleteGlobalRef(env, gPdfRenderClass); (*env)->DeleteGlobalRef(env, gSizeDClass); gPdfRenderClass = 0; } pdf_render_ifc_t *create_pdf_render_ifc() { LOGD("create_pdf_render_ifc"); pdf_render_st_t *self; // Set up the interface self = (pdf_render_st_t *) malloc(sizeof(pdf_render_st_t)); if (!self) return NULL; self->ifc.openDocument = openDocument; self->ifc.getPageAttributes = getPageAttributes; self->ifc.renderPageStripe = renderPageStripe; self->ifc.destroy = destroy; // Get the environment jint result = (*_JVM)->GetEnv(_JVM, (void **) &self->env, JNI_VERSION_1_6); if (result == JNI_EDETACHED) { self->needDetach = true; if ((*_JVM)->AttachCurrentThread(_JVM, &self->env, NULL) < 0) { LOGE("AttachCurrentThread failed"); free(self); return NULL; } } else { self->needDetach = false; } // Get the object jmethodID methodId = (*self->env)->GetStaticMethodID(self->env, gPdfRenderClass, "getInstance", "(Landroid/content/Context;)Lcom/android/bips/jni/PdfRender;"); jobject instance = (*self->env)->CallStaticObjectMethod(self->env, gPdfRenderClass, methodId, NULL); self->obj = (*self->env)->NewGlobalRef(self->env, instance); return &self->ifc; }