/* * Copyright 2011 Skia * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "com_skia_SkiaSampleRenderer.h" #include "SampleApp.h" #include "SkApplication.h" #include "SkCanvas.h" #include "SkDevice.h" #include "SkEvent.h" #include "SkWindow.h" #include #include "android/AndroidKeyToSkKey.h" /////////////////////////////////////////// ///////////////// Globals ///////////////// /////////////////////////////////////////// struct ActivityGlue { JNIEnv* m_env; jweak m_obj; jmethodID m_setTitle; jmethodID m_setSlideList; jmethodID m_addToDownloads; ActivityGlue() { m_env = NULL; m_obj = NULL; m_setTitle = NULL; m_setSlideList = NULL; m_addToDownloads = NULL; } } gActivityGlue; struct WindowGlue { jweak m_obj; jmethodID m_inval; jmethodID m_queueSkEvent; jmethodID m_startTimer; jmethodID m_getMSAASampleCount; WindowGlue() { m_obj = NULL; m_inval = NULL; m_queueSkEvent = NULL; m_startTimer = NULL; m_getMSAASampleCount = NULL; } } gWindowGlue; SampleWindow* gWindow; /////////////////////////////////////////// ///////////// SkOSWindow impl ///////////// /////////////////////////////////////////// bool SkOSWindow::attach(SkBackEndTypes /* attachType */, int /*msaaSampleCount*/, AttachmentInfo* info) { JNIEnv* env = gActivityGlue.m_env; if (!env || !gWindowGlue.m_getMSAASampleCount || !gWindowGlue.m_obj) { return false; } if (env->IsSameObject(gWindowGlue.m_obj, NULL)) { SkDebugf("ERROR: The JNI WeakRef to the Window is invalid"); return false; } info->fSampleCount = env->CallIntMethod(gWindowGlue.m_obj, gWindowGlue.m_getMSAASampleCount); // This is the value requested in SkiaSampleView.java. info->fStencilBits = 8; return true; } void SkOSWindow::onSetTitle(const char title[]) { JNIEnv* env = gActivityGlue.m_env; if (!env) { return; } if (env->IsSameObject(gActivityGlue.m_obj, NULL)) { SkDebugf("ERROR: The JNI WeakRef to the Activity is invalid"); return; } jstring string = env->NewStringUTF(title); env->CallVoidMethod(gActivityGlue.m_obj, gActivityGlue.m_setTitle, string); env->DeleteLocalRef(string); } void SkOSWindow::onHandleInval(const SkIRect& rect) { JNIEnv* env = gActivityGlue.m_env; if (!env || !gWindowGlue.m_inval || !gWindowGlue.m_obj) { return; } if (env->IsSameObject(gWindowGlue.m_obj, NULL)) { SkDebugf("ERROR: The JNI WeakRef to the Window is invalid"); return; } env->CallVoidMethod(gWindowGlue.m_obj, gWindowGlue.m_inval); } void SkOSWindow::onPDFSaved(const char title[], const char desc[], const char path[]) { JNIEnv* env = gActivityGlue.m_env; if (!env || !gActivityGlue.m_addToDownloads || !gActivityGlue.m_obj) { return; } if (env->IsSameObject(gActivityGlue.m_obj, NULL)) { SkDebugf("ERROR: The JNI WeakRef to the Activity is invalid"); return; } jstring jtitle = env->NewStringUTF(title); jstring jdesc = env->NewStringUTF(desc); jstring jpath = env->NewStringUTF(path); env->CallVoidMethod(gActivityGlue.m_obj, gActivityGlue.m_addToDownloads, jtitle, jdesc, jpath); env->DeleteLocalRef(jtitle); env->DeleteLocalRef(jdesc); env->DeleteLocalRef(jpath); } /////////////////////////////////////////// /////////////// SkEvent impl ////////////// /////////////////////////////////////////// void SkEvent::SignalQueueTimer(SkMSec ms) { JNIEnv* env = gActivityGlue.m_env; if (!env || !gWindowGlue.m_startTimer || !gWindowGlue.m_obj || !ms) { return; } if (env->IsSameObject(gWindowGlue.m_obj, NULL)) { SkDebugf("ERROR: The JNI WeakRef to the Window is invalid"); return; } env->CallVoidMethod(gWindowGlue.m_obj, gWindowGlue.m_startTimer, ms); } void SkEvent::SignalNonEmptyQueue() { JNIEnv* env = gActivityGlue.m_env; if (!env || !gWindowGlue.m_queueSkEvent || !gWindowGlue.m_obj) { return; } if (env->IsSameObject(gWindowGlue.m_obj, NULL)) { SkDebugf("ERROR: The JNI WeakRef to the Window is invalid"); return; } env->CallVoidMethod(gWindowGlue.m_obj, gWindowGlue.m_queueSkEvent); } /////////////////////////////////////////// ////////////////// JNI //////////////////// /////////////////////////////////////////// static jmethodID GetJMethod(JNIEnv* env, jclass clazz, const char name[], const char signature[]) { jmethodID m = env->GetMethodID(clazz, name, signature); if (!m) SkDebugf("Could not find Java method %s\n", name); return m; } JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_init(JNIEnv* env, jobject thiz, jobject jsampleActivity, jint msaaSampleCount) { // setup jni hooks to the java activity gActivityGlue.m_env = env; jclass clazz = env->FindClass("com/skia/SkiaSampleActivity"); gActivityGlue.m_obj = env->NewWeakGlobalRef(jsampleActivity); gActivityGlue.m_setTitle = GetJMethod(env, clazz, "setTitle", "(Ljava/lang/CharSequence;)V"); gActivityGlue.m_setSlideList = GetJMethod(env, clazz, "setSlideList", "([Ljava/lang/String;)V"); gActivityGlue.m_addToDownloads = GetJMethod(env, clazz, "addToDownloads", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); env->DeleteLocalRef(clazz); // setup jni hooks to the java renderer clazz = env->FindClass("com/skia/SkiaSampleRenderer"); gWindowGlue.m_obj = env->NewWeakGlobalRef(thiz); gWindowGlue.m_inval = GetJMethod(env, clazz, "requestRender", "()V"); gWindowGlue.m_queueSkEvent = GetJMethod(env, clazz, "queueSkEvent", "()V"); gWindowGlue.m_startTimer = GetJMethod(env, clazz, "startTimer", "(I)V"); gWindowGlue.m_getMSAASampleCount = GetJMethod(env, clazz, "getMSAASampleCount", "()I"); env->DeleteLocalRef(clazz); application_init(); SkTArray args; args.push_back("SampleApp"); // TODO: push ability to select skp dir into the UI args.push_back("--pictureDir"); args.push_back("/sdcard/skiabot/skia_skp"); SkString msaaSampleCountString; if (msaaSampleCount > 0) { args.push_back("--msaa"); msaaSampleCountString.appendS32(static_cast(msaaSampleCount)); args.push_back(msaaSampleCountString.c_str()); } gWindow = new SampleWindow(NULL, args.count(), const_cast(args.begin()), NULL); // send the list of slides up to the activity const int slideCount = gWindow->sampleCount(); jobjectArray slideList = env->NewObjectArray(slideCount, env->FindClass("java/lang/String"), env->NewStringUTF("")); for (int i = 0; i < slideCount; i++) { jstring slideTitle = env->NewStringUTF(gWindow->getSampleTitle(i).c_str()); env->SetObjectArrayElement(slideList, i, slideTitle); env->DeleteLocalRef(slideTitle); } env->CallVoidMethod(gActivityGlue.m_obj, gActivityGlue.m_setSlideList, slideList); env->DeleteLocalRef(slideList); } JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_term(JNIEnv* env, jobject thiz) { delete gWindow; gWindow = NULL; application_term(); if (gWindowGlue.m_obj) { env->DeleteWeakGlobalRef(gWindowGlue.m_obj); gWindowGlue.m_obj = NULL; } if (gActivityGlue.m_obj) { env->DeleteWeakGlobalRef(gActivityGlue.m_obj); gActivityGlue.m_obj = NULL; } } JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_draw( JNIEnv* env, jobject thiz) { if (!gWindow) return; gWindow->update(NULL); } JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_updateSize(JNIEnv* env, jobject thiz, jint w, jint h) { gWindow->resize(w, h); } JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_handleClick(JNIEnv* env, jobject thiz, jint owner, jfloat x, jfloat y, jint jstate) { SkView::Click::State state; switch(jstate) { case 0: // MotionEvent.ACTION_DOWN state = SkView::Click::kDown_State; break; case 1: // MotionEvent.ACTION_UP case 3: // MotionEvent.ACTION_CANCEL state = SkView::Click::kUp_State; break; case 2: // MotionEvent.ACTION_MOVE state = SkView::Click::kMoved_State; break; default: SkDebugf("motion event ignored\n"); return; } gWindow->handleClick(x, y, state, reinterpret_cast(owner)); } JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_nextSample( JNIEnv* env, jobject thiz) { gWindow->nextSample(); } JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_previousSample( JNIEnv* env, jobject thiz) { gWindow->previousSample(); } JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_goToSample( JNIEnv* env, jobject thiz, jint position) { gWindow->goToSample(position); } JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_toggleRenderingMode( JNIEnv* env, jobject thiz) { gWindow->toggleRendering(); } JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_showOverview( JNIEnv* env, jobject thiz) { gWindow->showOverview(); } JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_toggleSlideshow( JNIEnv* env, jobject thiz) { gWindow->toggleSlideshow(); } JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_toggleFPS( JNIEnv* env, jobject thiz) { gWindow->toggleFPS(); } JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_toggleTiling( JNIEnv* env, jobject thiz) { gWindow->handleChar('t'); } JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_toggleBBox( JNIEnv* env, jobject thiz) { gWindow->handleChar('b'); } JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_processSkEvent( JNIEnv* env, jobject thiz) { if (SkEvent::ProcessEvent()) { SkEvent::SignalNonEmptyQueue(); } } JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_serviceQueueTimer( JNIEnv* env, jobject thiz) { SkEvent::ServiceQueueTimer(); } JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_saveToPDF( JNIEnv* env, jobject thiz) { gWindow->saveToPdf(); } JNIEXPORT void JNICALL Java_com_skia_SkiaSampleRenderer_postInval( JNIEnv* env, jobject thiz) { gWindow->postInvalDelay(); }