You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
5.7 KiB
168 lines
5.7 KiB
/*
|
|
* 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;
|
|
} |