/* * Copyright (C) 2011 Skia * * 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 "SkCanvas.h" #include "GraphicsJNI.h" #include "SkEvent.h" #include "SkWindow.h" #include "SkApplication.h" #include "utils/android/AndroidKeyToSkKey.h" /////////////////////////////////////////// ///////////////// Globals ///////////////// /////////////////////////////////////////// struct ActivityGlue { JNIEnv* m_env; jweak m_obj; jmethodID m_setTitle; ActivityGlue() { m_env = NULL; m_obj = NULL; m_setTitle = NULL; } } gActivityGlue; struct WindowGlue { jweak m_obj; jmethodID m_inval; WindowGlue() { m_obj = NULL; m_inval = NULL; } } gWindowGlue; SkOSWindow* gWindow; /////////////////////////////////////////// ///////////// SkOSWindow impl ///////////// /////////////////////////////////////////// void SkOSWindow::onSetTitle(const char title[]) { if (gActivityGlue.m_env) { JNIEnv* env = gActivityGlue.m_env; jstring string = env->NewStringUTF(title); env->CallVoidMethod(gActivityGlue.m_obj, gActivityGlue.m_setTitle, string); env->DeleteLocalRef(string); } } void SkOSWindow::onHandleInval(const SkIRect& rect) { if (!gActivityGlue.m_env || !gWindowGlue.m_inval || !gWindowGlue.m_obj) { return; } gActivityGlue.m_env->CallVoidMethod(gWindowGlue.m_obj, gWindowGlue.m_inval, rect.fLeft, rect.fTop, rect.fRight, rect.fBottom); } /////////////////////////////////////////// /////////////// SkEvent impl ////////////// /////////////////////////////////////////// void SkEvent::SignalQueueTimer(SkMSec) {} void SkEvent::SignalNonEmptyQueue() {} /////////////////////////////////////////// ////////////////// 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; } extern "C" { JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_drawToCanvas( JNIEnv* env, jobject thiz, jobject jcanvas); JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_init( JNIEnv* env, jobject thiz); JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_term( JNIEnv* env, jobject thiz); JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_updateSize( JNIEnv* env, jobject thiz, jint w, jint h); JNIEXPORT bool JNICALL Java_com_skia_sampleapp_SampleApp_handleKeyDown( JNIEnv* env, jobject thiz, jint keyCode, jint uni); JNIEXPORT bool JNICALL Java_com_skia_sampleapp_SampleApp_handleKeyUp( JNIEnv* env, jobject thiz, jint keyCode); JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_handleClick( JNIEnv* env, jobject thiz, jint x, jint y, jint state); JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_createOSWindow( JNIEnv* env, jobject thiz, jobject jsampleView); }; JNIEXPORT bool JNICALL Java_com_skia_sampleapp_SampleApp_handleKeyDown( JNIEnv* env, jobject thiz, jint keyCode, jint uni) { bool handled = gWindow->handleKey(AndroidKeycodeToSkKey(keyCode)); handled |= gWindow->handleChar((SkUnichar) uni); return handled; } JNIEXPORT bool JNICALL Java_com_skia_sampleapp_SampleApp_handleKeyUp(JNIEnv* env, jobject thiz, jint keyCode) { return gWindow->handleKeyUp(AndroidKeycodeToSkKey(keyCode)); } JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_handleClick(JNIEnv* env, jobject thiz, jint x, jint 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); } JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_updateSize(JNIEnv* env, jobject thiz, jint w, jint h) { gWindow->resize(w, h); } JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_createOSWindow( JNIEnv* env, jobject thiz, jobject jsampleView) { gWindow = create_sk_window(NULL); // Only using a method on View. jclass clazz = gActivityGlue.m_env->FindClass("android/view/View"); gWindowGlue.m_obj = gActivityGlue.m_env->NewWeakGlobalRef(jsampleView); gWindowGlue.m_inval = GetJMethod(gActivityGlue.m_env, clazz, "invalidate", "(IIII)V"); gActivityGlue.m_env->DeleteLocalRef(clazz); } JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_init(JNIEnv* env, jobject thiz) { gActivityGlue.m_env = env; // Only using a method on Activity. jclass clazz = env->FindClass("android/app/Activity"); gActivityGlue.m_obj = env->NewWeakGlobalRef(thiz); gActivityGlue.m_setTitle = GetJMethod(env, clazz, "setTitle", "(Ljava/lang/CharSequence;)V"); env->DeleteLocalRef(clazz); application_init(); } JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_term(JNIEnv* env, jobject thiz) { 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; } delete gWindow; gWindow = NULL; } JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_drawToCanvas( JNIEnv* env, jobject thiz, jobject jcanvas) { if (!gWindow) return; gWindow->update(NULL); SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas); canvas->drawBitmap(gWindow->getBitmap(), 0, 0); }