1 /*
2 * Copyright (C) 2011 Skia
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18 #include <jni.h>
19
20 #include "SkCanvas.h"
21 #include "GraphicsJNI.h"
22 #include "SkEvent.h"
23 #include "SkWindow.h"
24 #include "SkApplication.h"
25 #include "utils/android/AndroidKeyToSkKey.h"
26
27 ///////////////////////////////////////////
28 ///////////////// Globals /////////////////
29 ///////////////////////////////////////////
30
31 struct ActivityGlue {
32 JNIEnv* m_env;
33 jweak m_obj;
34 jmethodID m_setTitle;
ActivityGlueActivityGlue35 ActivityGlue() {
36 m_env = NULL;
37 m_obj = NULL;
38 m_setTitle = NULL;
39 }
40 } gActivityGlue;
41
42 struct WindowGlue {
43 jweak m_obj;
44 jmethodID m_inval;
WindowGlueWindowGlue45 WindowGlue() {
46 m_obj = NULL;
47 m_inval = NULL;
48 }
49 } gWindowGlue;
50
51 SkOSWindow* gWindow;
52
53 ///////////////////////////////////////////
54 ///////////// SkOSWindow impl /////////////
55 ///////////////////////////////////////////
56
onSetTitle(const char title[])57 void SkOSWindow::onSetTitle(const char title[])
58 {
59 if (gActivityGlue.m_env) {
60 JNIEnv* env = gActivityGlue.m_env;
61 jstring string = env->NewStringUTF(title);
62 env->CallVoidMethod(gActivityGlue.m_obj, gActivityGlue.m_setTitle,
63 string);
64 env->DeleteLocalRef(string);
65 }
66 }
67
onHandleInval(const SkIRect & rect)68 void SkOSWindow::onHandleInval(const SkIRect& rect)
69 {
70 if (!gActivityGlue.m_env || !gWindowGlue.m_inval || !gWindowGlue.m_obj) {
71 return;
72 }
73 gActivityGlue.m_env->CallVoidMethod(gWindowGlue.m_obj, gWindowGlue.m_inval,
74 rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
75 }
76
77 ///////////////////////////////////////////
78 /////////////// SkEvent impl //////////////
79 ///////////////////////////////////////////
80
SignalQueueTimer(SkMSec)81 void SkEvent::SignalQueueTimer(SkMSec) {}
82
SignalNonEmptyQueue()83 void SkEvent::SignalNonEmptyQueue() {}
84
85 ///////////////////////////////////////////
86 ////////////////// JNI ////////////////////
87 ///////////////////////////////////////////
88
GetJMethod(JNIEnv * env,jclass clazz,const char name[],const char signature[])89 static jmethodID GetJMethod(JNIEnv* env, jclass clazz, const char name[],
90 const char signature[])
91 {
92 jmethodID m = env->GetMethodID(clazz, name, signature);
93 if (!m) SkDebugf("Could not find Java method %s\n", name);
94 return m;
95 }
96
97 extern "C" {
98 JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_drawToCanvas(
99 JNIEnv* env, jobject thiz, jobject jcanvas);
100 JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_init(
101 JNIEnv* env, jobject thiz);
102 JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_term(
103 JNIEnv* env, jobject thiz);
104 JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_updateSize(
105 JNIEnv* env, jobject thiz, jint w, jint h);
106 JNIEXPORT bool JNICALL Java_com_skia_sampleapp_SampleApp_handleKeyDown(
107 JNIEnv* env, jobject thiz, jint keyCode, jint uni);
108 JNIEXPORT bool JNICALL Java_com_skia_sampleapp_SampleApp_handleKeyUp(
109 JNIEnv* env, jobject thiz, jint keyCode);
110 JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_handleClick(
111 JNIEnv* env, jobject thiz, jint x, jint y, jint state);
112 JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_createOSWindow(
113 JNIEnv* env, jobject thiz, jobject jsampleView);
114 };
115
Java_com_skia_sampleapp_SampleApp_handleKeyDown(JNIEnv * env,jobject thiz,jint keyCode,jint uni)116 JNIEXPORT bool JNICALL Java_com_skia_sampleapp_SampleApp_handleKeyDown(
117 JNIEnv* env, jobject thiz, jint keyCode, jint uni)
118 {
119 bool handled = gWindow->handleKey(AndroidKeycodeToSkKey(keyCode));
120 handled |= gWindow->handleChar((SkUnichar) uni);
121 return handled;
122 }
123
Java_com_skia_sampleapp_SampleApp_handleKeyUp(JNIEnv * env,jobject thiz,jint keyCode)124 JNIEXPORT bool JNICALL Java_com_skia_sampleapp_SampleApp_handleKeyUp(JNIEnv* env,
125 jobject thiz, jint keyCode)
126 {
127 return gWindow->handleKeyUp(AndroidKeycodeToSkKey(keyCode));
128 }
129
Java_com_skia_sampleapp_SampleApp_handleClick(JNIEnv * env,jobject thiz,jint x,jint y,jint jstate)130 JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_handleClick(JNIEnv* env,
131 jobject thiz, jint x, jint y, jint jstate)
132 {
133 SkView::Click::State state;
134 switch(jstate) {
135 case 0: // MotionEvent.ACTION_DOWN
136 state = SkView::Click::kDown_State;
137 break;
138 case 1: // MotionEvent.ACTION_UP
139 case 3: // MotionEvent.ACTION_CANCEL
140 state = SkView::Click::kUp_State;
141 break;
142 case 2: // MotionEvent.ACTION_MOVE
143 state = SkView::Click::kMoved_State;
144 break;
145 default:
146 SkDebugf("motion event ignored\n");
147 return;
148 }
149 gWindow->handleClick(x, y, state);
150 }
151
Java_com_skia_sampleapp_SampleApp_updateSize(JNIEnv * env,jobject thiz,jint w,jint h)152 JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_updateSize(JNIEnv* env,
153 jobject thiz, jint w, jint h)
154 {
155 gWindow->resize(w, h);
156 }
157
Java_com_skia_sampleapp_SampleApp_createOSWindow(JNIEnv * env,jobject thiz,jobject jsampleView)158 JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_createOSWindow(
159 JNIEnv* env, jobject thiz, jobject jsampleView)
160 {
161 gWindow = create_sk_window(NULL);
162 // Only using a method on View.
163 jclass clazz = gActivityGlue.m_env->FindClass("android/view/View");
164 gWindowGlue.m_obj = gActivityGlue.m_env->NewWeakGlobalRef(jsampleView);
165 gWindowGlue.m_inval = GetJMethod(gActivityGlue.m_env, clazz, "invalidate",
166 "(IIII)V");
167 gActivityGlue.m_env->DeleteLocalRef(clazz);
168 }
169
Java_com_skia_sampleapp_SampleApp_init(JNIEnv * env,jobject thiz)170 JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_init(JNIEnv* env,
171 jobject thiz)
172 {
173 gActivityGlue.m_env = env;
174 // Only using a method on Activity.
175 jclass clazz = env->FindClass("android/app/Activity");
176 gActivityGlue.m_obj = env->NewWeakGlobalRef(thiz);
177 gActivityGlue.m_setTitle = GetJMethod(env, clazz, "setTitle",
178 "(Ljava/lang/CharSequence;)V");
179 env->DeleteLocalRef(clazz);
180
181 application_init();
182 }
183
Java_com_skia_sampleapp_SampleApp_term(JNIEnv * env,jobject thiz)184 JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_term(JNIEnv* env,
185 jobject thiz)
186 {
187 application_term();
188 if (gWindowGlue.m_obj) {
189 env->DeleteWeakGlobalRef(gWindowGlue.m_obj);
190 gWindowGlue.m_obj = NULL;
191 }
192 if (gActivityGlue.m_obj) {
193 env->DeleteWeakGlobalRef(gActivityGlue.m_obj);
194 gActivityGlue.m_obj = NULL;
195 }
196 delete gWindow;
197 gWindow = NULL;
198 }
199
200
Java_com_skia_sampleapp_SampleApp_drawToCanvas(JNIEnv * env,jobject thiz,jobject jcanvas)201 JNIEXPORT void JNICALL Java_com_skia_sampleapp_SampleApp_drawToCanvas(
202 JNIEnv* env, jobject thiz, jobject jcanvas)
203 {
204 if (!gWindow) return;
205 gWindow->update(NULL);
206 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
207 canvas->drawBitmap(gWindow->getBitmap(), 0, 0);
208 }
209