PageRenderTime 103ms CodeModel.GetById 34ms app.highlight 64ms RepoModel.GetById 1ms app.codeStats 0ms

/src/compiler/android-ndk/jni/ftkapp/ftk_jni.cpp

http://ftk.googlecode.com/
C++ | 544 lines | 460 code | 79 blank | 5 comment | 46 complexity | d0c540bef07ba948e8e7c812377a3b93 MD5 | raw file
  1
  2#include <jni.h>
  3#include <android/log.h>
  4#include <unistd.h>
  5#include "ftk.h"
  6#include "ftk_jni.h"
  7#include "ftk_log.h"
  8#include "ftk_key.h"
  9#include "ftk_event.h"
 10#include "ftk_globals.h"
 11#include "ftk_display.h"
 12#include "ftk_display_rotate.h"
 13
 14typedef struct _FtkJni
 15{
 16	JNIEnv* env;
 17
 18	jclass activity;
 19	jmethodID get_asset_file_descriptor;
 20	jmethodID decode_image;
 21	jmethodID init_egl;
 22	jmethodID create_egl_surface;
 23	jmethodID destroy_egl_surface;
 24	jmethodID flip_egl;
 25	jmethodID draw_bitmap;
 26	jmethodID show_keyboard;
 27	jmethodID hide_keyboard;
 28	jmethodID show_input_method_picker;
 29
 30	jmethodID get_file_descriptor;
 31	jmethodID get_start_offset;
 32	jmethodID get_length;
 33	jmethodID close_file_descriptor;
 34
 35	jfieldID descriptor;
 36
 37	jmethodID get_pixels;
 38	jmethodID get_width;
 39	jmethodID get_height;
 40
 41	jintArray pixels;
 42
 43	int render_enabled;
 44	int surface_valid;
 45	FtkEvent event;
 46}FtkJni;
 47
 48FtkJni jni;
 49
 50#if 0
 51FTK_KEY_EXCLAM
 52FTK_KEY_QUOTEDBL
 53FTK_KEY_NUMBERSIGN
 54FTK_KEY_DOLLAR
 55FTK_KEY_PERCENT
 56FTK_KEY_AMPERSAND
 57FTK_KEY_QUOTERIGHT
 58FTK_KEY_PARENLEFT
 59FTK_KEY_PARENRIGHT
 60FTK_KEY_ASTERISK
 61FTK_KEY_COLON
 62FTK_KEY_LESS
 63FTK_KEY_GREATER
 64FTK_KEY_QUESTION
 65FTK_KEY_ASCIICIRCUM
 66FTK_KEY_UNDERSCORE
 67FTK_KEY_QUOTELEFT
 68FTK_KEY_LEFTBRACE
 69FTK_KEY_OR
 70FTK_KEY_RIGHTBRACE
 71FTK_KEY_NOT
 72FTK_KEY_DOT
 73FTK_KEY_HOME
 74FTK_KEY_PRIOR
 75FTK_KEY_NEXT
 76FTK_KEY_END
 77FTK_KEY_BEGIN
 78FTK_KEY_INSERT
 79FTK_KEY_ESC
 80FTK_KEY_RIGHTCTRL
 81FTK_KEY_LEFTCTRL
 82FTK_KEY_CAPSLOCK
 83FTK_KEY_SEND
 84FTK_KEY_REPLY
 85FTK_KEY_SAVE
 86FTK_KEY_BATTERY
 87FTK_KEY_BLUETOOTH
 88FTK_KEY_WLAN
 89FTK_KEY_DELETE
 90#endif
 91
 92static const int key_maps[] =
 93{
 94    /*KeyCodeUnknown[0] = */0,
 95    /*KeyCodeSoftLeft[1] = */0,
 96    /*KeyCodeSoftRight[2] = */0,
 97    /*KeyCodeHome[3] = */0,
 98    /*KeyCodeBack[4] = */0,//FTK_KEY_RETURN,
 99    /*KeyCodeCall[5] = */0,
100    /*KeyCodeEndCall[6] = */0,
101    /*KeyCode0[7] = */FTK_KEY_0,
102    /*KeyCode1[8] = */FTK_KEY_1,
103    /*KeyCode2[9] = */FTK_KEY_2,
104    /*KeyCode3[10] = */FTK_KEY_3,
105    /*KeyCode4[11] = */FTK_KEY_4,
106    /*KeyCode5[12] = */FTK_KEY_5,
107    /*KeyCode6[13] = */FTK_KEY_6,
108    /*KeyCode7[14] = */FTK_KEY_7,
109    /*KeyCode8[15] = */FTK_KEY_8,
110    /*KeyCode9[16] = */FTK_KEY_9,
111    /*KeyCodeStar[17] = */0,
112    /*KeyCodePound[18] = */0,
113    /*KeyCodeDpadUp[19] = */FTK_KEY_UP,
114    /*KeyCodeDpadDown[20] = */FTK_KEY_DOWN,
115    /*KeyCodeDpadLeft[21] = */FTK_KEY_LEFT,
116    /*KeyCodeDpadRight[22] = */FTK_KEY_RIGHT,
117    /*KeyCodeDpadCenter[23] = */0,
118    /*KeyCodeVolumeUp[24] = */0,
119    /*KeyCodeVolumeDown[25] = */0,
120    /*KeyCodePower[26] = */FTK_KEY_POWER,
121    /*KeyCodeCamera[27] = */0,
122    /*KeyCodeClear[28] = */0,
123    /*KeyCodeA[29] = */FTK_KEY_A,
124    /*KeyCodeB[30] = */FTK_KEY_B,
125    /*KeyCodeC[31] = */FTK_KEY_C,
126    /*KeyCodeD[32] = */FTK_KEY_D,
127    /*KeyCodeE[33] = */FTK_KEY_E,
128    /*KeyCodeF[34] = */FTK_KEY_F,
129    /*KeyCodeG[35] = */FTK_KEY_G,
130    /*KeyCodeH[36] = */FTK_KEY_H,
131    /*KeyCodeI[37] = */FTK_KEY_I,
132    /*KeyCodeJ[38] = */FTK_KEY_J,
133    /*KeyCodeK[39] = */FTK_KEY_K,
134    /*KeyCodeL[40] = */FTK_KEY_L,
135    /*KeyCodeM[41] = */FTK_KEY_M,
136    /*KeyCodeN[42] = */FTK_KEY_N,
137    /*KeyCodeO[43] = */FTK_KEY_O,
138    /*KeyCodeP[44] = */FTK_KEY_P,
139    /*KeyCodeQ[45] = */FTK_KEY_Q,
140    /*KeyCodeR[46] = */FTK_KEY_R,
141    /*KeyCodeS[47] = */FTK_KEY_S,
142    /*KeyCodeT[48] = */FTK_KEY_T,
143    /*KeyCodeU[49] = */FTK_KEY_U,
144    /*KeyCodeV[50] = */FTK_KEY_V,
145    /*KeyCodeW[51] = */FTK_KEY_W,
146    /*KeyCodeX[52] = */FTK_KEY_X,
147    /*KeyCodeY[53] = */FTK_KEY_Y,
148    /*KeyCodeZ[54] = */FTK_KEY_Z,
149    /*KeyCodeComma[55] = */FTK_KEY_COMMA,
150    /*KeyCodePeriod[56] = */FTK_KEY_PERIOD,
151    /*KeyCodeAltLeft[57] = */FTK_KEY_LEFTALT,
152    /*KeyCodeAltRight[58] = */FTK_KEY_RIGHTALT,
153    /*KeyCodeShiftLeft[59] = */FTK_KEY_LEFTSHIFT,
154    /*KeyCodeShiftRight[60] = */FTK_KEY_RIGHTSHIFT,
155    /*KeyCodeTab[61] = */FTK_KEY_TAB,
156    /*KeyCodeSpace[62] = */FTK_KEY_SPACE,
157    /*KeyCodeSym[63] = */0,
158    /*KeyCodeExplorer[64] = */0,
159    /*KeyCodeEnvelope[65] = */0,
160    /*KeyCodeNewline[66] = */0,
161    /*KeyCodeDel[67] = */FTK_KEY_BACKSPACE,
162    /*KeyCodeGrave[68] = */FTK_KEY_GRAVE,
163    /*KeyCodeMinus[69] = */FTK_KEY_MINUS,
164    /*KeyCodeEquals[70] = */FTK_KEY_EQUAL,
165    /*KeyCodeLeftBracket[71] = */FTK_KEY_BRACKETLEFT,
166    /*KeyCodeRightBracket[72] = */FTK_KEY_BRACKETRIGHT,
167    /*KeyCodeBackslash[73] = */FTK_KEY_BACKSLASH,
168    /*KeyCodeSemicolon[74] = */FTK_KEY_SEMICOLON,
169    /*KeyCodeApostrophe[75] = */FTK_KEY_APOSTROPHE,
170    /*KeyCodeSlash[76] = */FTK_KEY_SLASH,
171    /*KeyCodeAt[77] = */FTK_KEY_AT,
172    /*KeyCodeNum[78] = */0,
173    /*KeyCodeHeadSetHook[79] = */0,
174    /*KeyCodeFocus[80] = */0,
175    /*KeyCodePlus[81] = */FTK_KEY_PLUS,
176    /*KeyCodeMenu[82] = */FTK_KEY_MENU,
177    /*KeyCodeNotification[83] = */0,
178    /*KeyCodeSearch[84] = */0,
179    /*KeyCodePlayPause[85] = */0,
180    /*KeyCodeStop[86] = */0,
181    /*KeyCodeNextSong[87] = */0,
182    /*KeyCodePreviousSong[88] = */0,
183    /*KeyCodeRewind[89] = */0,
184    /*KeyCodeForward[90] = */0,
185    /*KeyCodeMute[91] = */0,
186    /*KeyCodePageUp[92] = */FTK_KEY_PAGEUP,
187    /*KeyCodePageDown[93] = */FTK_KEY_PAGEDOWN,
188    /*KeyCodePictSymbols[94] = */0,
189    /*KeyCodeSwitchCharset[95] = */0
190};
191
192/******************************************************************************/
193
194extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
195{
196	JNIEnv* env = NULL;
197
198	ftk_logd("JNI: OnLoad()");
199
200	if(vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK)
201	{
202		return -1;
203	}
204
205	jni.env = env;
206
207	jclass cls = jni.env->FindClass("org/libftk/app/FtkActivity");
208	jni.activity = (jclass)jni.env->NewGlobalRef(cls);
209
210	jni.get_asset_file_descriptor = jni.env->GetStaticMethodID(cls, "getAssetFileDescriptor",
211		"(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor;");
212	jni.decode_image = jni.env->GetStaticMethodID(cls, "decodeImage", "(Ljava/lang/String;)Landroid/graphics/Bitmap;");
213
214	jni.init_egl = jni.env->GetStaticMethodID(cls, "initEGL", "()V");
215	jni.create_egl_surface = jni.env->GetStaticMethodID(cls, "createEGLSurface", "()V");
216	jni.destroy_egl_surface = jni.env->GetStaticMethodID(cls, "destroyEGLSurface", "()V");
217	jni.flip_egl = jni.env->GetStaticMethodID(cls, "flipEGL", "()V");
218	jni.draw_bitmap = jni.env->GetStaticMethodID(cls, "drawBitmap", "([IIIIIII)V");
219
220	jni.show_keyboard = jni.env->GetStaticMethodID(cls, "showKeyboard", "()V");
221	jni.hide_keyboard = jni.env->GetStaticMethodID(cls, "hideKeyboard", "()V");
222	jni.show_input_method_picker = jni.env->GetStaticMethodID(cls, "showInputMethodPicker", "()V");
223
224	cls = jni.env->FindClass("android/content/res/AssetFileDescriptor");
225	jni.get_file_descriptor = jni.env->GetMethodID(cls, "getFileDescriptor", "()Ljava/io/FileDescriptor;");
226	jni.get_start_offset = jni.env->GetMethodID(cls, "getStartOffset", "()J");
227	jni.get_length = jni.env->GetMethodID(cls, "getLength", "()J");
228	jni.close_file_descriptor = jni.env->GetMethodID(cls, "close", "()V");
229
230	cls = jni.env->FindClass("java/io/FileDescriptor");
231	jni.descriptor = jni.env->GetFieldID(cls, "descriptor", "I");
232
233	cls = jni.env->FindClass("android/graphics/Bitmap");
234	jni.get_pixels = jni.env->GetMethodID(cls, "getPixels", "([IIIIIII)V");
235	jni.get_width = jni.env->GetMethodID(cls, "getWidth", "()I");
236	jni.get_height = jni.env->GetMethodID(cls, "getHeight", "()I");
237
238	if(!jni.get_asset_file_descriptor || !jni.decode_image
239		|| !jni.init_egl || !jni.create_egl_surface || !jni.destroy_egl_surface || !jni.flip_egl || !jni.draw_bitmap
240		|| !jni.show_keyboard || !jni.hide_keyboard || !jni.show_input_method_picker
241		|| !jni.get_file_descriptor || !jni.get_start_offset || !jni.get_length || !jni.close_file_descriptor
242		|| !jni.descriptor
243		|| !jni.get_pixels || !jni.get_width || !jni.get_height)
244	{
245		ftk_logd("null method or field id");
246		return -1;
247	}
248
249	return JNI_VERSION_1_4;
250}
251
252extern "C" void Java_org_libftk_app_FtkActivity_nativeInit(JNIEnv* env, jobject obj)
253{
254	int argc, rv;
255	char* argv[2];
256
257	ftk_logd("native init");
258
259	jni.env = env;
260
261	argv[0] = (char *) "ftk";
262	argv[1] = NULL;
263	argc = 1;
264	rv = FTK_MAIN(argc, argv);
265
266	env->DeleteGlobalRef(jni.pixels);
267	env->DeleteGlobalRef(jni.activity);
268}
269
270extern "C" void Java_org_libftk_app_FtkActivity_nativeQuit(JNIEnv* env, jobject obj)
271{
272	FTK_QUIT();
273	ftk_logd("native quit");
274}
275
276extern "C" void Java_org_libftk_app_FtkActivity_nativeEnableRender(JNIEnv* env, jobject obj)
277{
278	jni.render_enabled = 1;
279}
280
281extern "C" void Java_org_libftk_app_FtkActivity_nativeDisableRender(JNIEnv* env, jobject obj)
282{
283	jni.render_enabled = 0;
284	jni.surface_valid = 0;
285}
286
287extern "C" void Java_org_libftk_app_FtkActivity_onNativeKey(JNIEnv* env, jobject obj, jint action, jint keyCode)
288{
289	ftk_logd("native key action:%d keyCode:%d", action, keyCode);
290
291	if(action == 2)
292	{
293		return;
294	}
295	jni.event.type = action == 0 ? FTK_EVT_KEY_DOWN : FTK_EVT_KEY_UP;
296	jni.event.u.key.code = key_maps[keyCode];
297	ftk_wnd_manager_queue_event_auto_rotate(ftk_default_wnd_manager(), &jni.event);
298}
299
300extern "C" void Java_org_libftk_app_FtkActivity_onNativeCommitText(JNIEnv* env, jobject obj, jstring text, jint newCursorPosition)
301{
302	char* buf;
303	jsize len;
304	const char *str;
305
306	len = env->GetStringUTFLength(text);
307	str = env->GetStringUTFChars(text, NULL);
308	buf = (char*)FTK_ALLOC(len + 1);
309	memcpy(buf, str, len);
310	buf[len] = '\0';
311	env->ReleaseStringUTFChars(text, str);
312
313	memset(&jni.event, 0, sizeof(FtkEvent));
314	jni.event.u.extra = buf;
315	jni.event.type = FTK_EVT_OS_IM_COMMIT;
316	ftk_wnd_manager_queue_event_auto_rotate(ftk_default_wnd_manager(), &jni.event);
317}
318
319extern "C" void Java_org_libftk_app_FtkActivity_onNativeTouch(JNIEnv* env, jobject obj, jint action, jfloat x, jfloat y, jfloat p)
320{
321	ftk_logd("native touch event %d @ %f/%f, pressure %f", action, x, y, p);
322	memset(&jni.event, 0, sizeof(FtkEvent));
323	if(action==0)
324	{
325		jni.event.type = FTK_EVT_MOUSE_DOWN;
326	}
327	else if(action == 1 || action == 3)
328	{
329		jni.event.type = FTK_EVT_MOUSE_UP;
330	}
331	else if(action == 2)
332	{
333		jni.event.type = FTK_EVT_MOUSE_MOVE;
334	}
335	else
336	{
337		return;
338	}
339	jni.event.u.mouse.x = x;
340	jni.event.u.mouse.y = y;
341	ftk_wnd_manager_queue_event_auto_rotate(ftk_default_wnd_manager(), &jni.event);
342}
343
344extern "C" void Java_org_libftk_app_FtkActivity_nativeSetScreenSize(JNIEnv* env, jobject obj, jint width, jint height)
345{
346	ftk_logd("nativeSetScreenSize() %dX%d", width, height);
347	Android_SetScreenResolution(width, height);
348
349	jintArray temp = (jintArray)env->NewIntArray(width * height);
350	jni.pixels = (jintArray)env->NewGlobalRef(temp);
351	env->DeleteLocalRef(temp);
352}
353
354extern "C" void Java_org_libftk_app_FtkActivity_onNativeResize(JNIEnv* env, jobject obj, jint width, jint height, jint format)
355{
356	int w, h;
357	FtkDisplay* display = NULL;
358	FtkRotate r = FTK_ROTATE_0;
359
360	display = ftk_default_display();
361	r = ftk_display_get_rotate(display);
362	w = ftk_display_width(display);
363	h = ftk_display_height(display);
364
365	ftk_logd("onNativeResize() old size:%dX%d new size:%dX%d format:%d", w, h, width, height, format);
366
367	if(width != w && height != h)
368	{
369		memset(&jni.event, 0, sizeof(FtkEvent));
370		if(r == FTK_ROTATE_0)
371		{
372			jni.event.u.extra = (void*)FTK_ROTATE_90;
373		}
374		else
375		{
376			jni.event.u.extra = (void*)FTK_ROTATE_0;
377		}
378		jni.event.type = FTK_EVT_OS_SCREEN_ROTATED;
379		//ftk_wnd_manager_queue_event_auto_rotate(ftk_default_wnd_manager(), &jni.event);
380	}
381
382	memset(&jni.event, 0, sizeof(FtkEvent));
383	jni.event.type = FTK_EVT_RELAYOUT_WND;
384	ftk_wnd_manager_queue_event_auto_rotate(ftk_default_wnd_manager(), &jni.event);
385}
386
387/******************************************************************************/
388
389void Android_Log(const char* fmt, ...)
390{
391	va_list ap;
392	va_start(ap, fmt);
393	__android_log_vprint(ANDROID_LOG_INFO, "FTK", fmt, ap);
394	va_end(ap);
395}
396
397int Android_OpenAsset(const char* filename, size_t* size)
398{
399	int fd;
400	jlong asset_offset, asset_size;
401	jstring file;
402	jobject asset_fd, descriptor;
403
404	//ftk_logd("%s", filename);
405
406	file = jni.env->NewStringUTF(filename);
407	asset_fd = jni.env->CallStaticObjectMethod(jni.activity, jni.get_asset_file_descriptor, file);
408	jni.env->DeleteLocalRef(file);
409
410	descriptor = jni.env->CallObjectMethod(asset_fd, jni.get_file_descriptor);
411	asset_offset = jni.env->CallLongMethod(asset_fd, jni.get_start_offset);
412	asset_size = jni.env->CallLongMethod(asset_fd, jni.get_length);
413
414	ftk_logd("%s %d", filename, (int)asset_size);
415
416	fd = dup(jni.env->GetIntField(descriptor, jni.descriptor));
417
418	jni.env->CallVoidMethod(asset_fd, jni.close_file_descriptor);
419	jni.env->DeleteLocalRef(descriptor);
420	jni.env->DeleteLocalRef(asset_fd);
421
422	lseek(fd, (int)asset_offset, SEEK_SET);
423
424	*size = asset_size;
425
426	return fd;
427}
428
429FtkBitmap* Android_LoadImage(const char* filename)
430{
431	jint width, height;
432	jint* pixels;
433	jstring file;
434	jobject image;
435	jintArray temp;
436	FtkBitmap* bitmap;
437	FtkColor bg = {0};
438	FtkColor* dst;
439
440	//ftk_logd("%s", filename);
441
442	file = jni.env->NewStringUTF(filename);
443	image = jni.env->CallStaticObjectMethod(jni.activity, jni.decode_image, file);
444	jni.env->DeleteLocalRef(file);
445
446	if(image == NULL)
447	{
448		return NULL;
449	}
450
451	width = jni.env->CallIntMethod(image, jni.get_width);
452	height = jni.env->CallIntMethod(image, jni.get_height);
453
454	ftk_logd("%s: %dX%d", filename, width, height);
455
456	temp = jni.env->NewIntArray(width * height);
457	jni.env->CallVoidMethod(image, jni.get_pixels, temp, 0, width, 0, 0, width, height);
458	pixels = jni.env->GetIntArrayElements(temp, NULL);
459
460	bg.a = 0xff;
461	bitmap = ftk_bitmap_create(width, height, bg);
462	dst = ftk_bitmap_lock(bitmap);
463
464	memcpy(dst, pixels, sizeof(FtkColor) * width * height);
465
466	jni.env->ReleaseIntArrayElements(temp, pixels, 0);
467	jni.env->DeleteLocalRef(temp);
468	jni.env->DeleteLocalRef(image);
469
470	return bitmap;
471}
472
473void Android_InitEGL()
474{
475	ftk_logd("Android_InitEGL()");
476	jni.env->CallStaticVoidMethod(jni.activity, jni.init_egl);
477}
478
479Ret Android_PreRender()
480{
481	if(!jni.render_enabled)
482	{
483		if(jni.surface_valid)
484		{
485			jni.env->CallStaticVoidMethod(jni.activity, jni.destroy_egl_surface);
486		}
487		return RET_FAIL;
488	}
489	if(!jni.surface_valid)
490	{
491		jni.env->CallStaticVoidMethod(jni.activity, jni.create_egl_surface);
492		jni.surface_valid = 1;
493	}
494	return RET_OK;
495}
496
497void Android_Render()
498{
499	if(!jni.render_enabled || !jni.surface_valid)
500	{
501		return;
502	}
503	jni.env->CallStaticVoidMethod(jni.activity, jni.flip_egl);
504}
505
506int* Android_GetBitmapPixels()
507{
508	return (int*)jni.env->GetIntArrayElements(jni.pixels, NULL);
509}
510
511void Android_ReleaseBitmapPixels(int* pixels)
512{
513	jni.env->ReleaseIntArrayElements(jni.pixels, pixels, 0);
514}
515
516void Android_DrawBitmap(int offset, int stride, int x, int y, int width, int height)
517{
518	if(!jni.render_enabled)
519	{
520		return;
521	}
522
523	jintArray temp = (jintArray)jni.env->NewLocalRef(jni.pixels);
524	jni.env->CallStaticVoidMethod(jni.activity, jni.draw_bitmap, temp, offset, stride, x, y, width, height);
525	jni.env->DeleteLocalRef(temp); // TODO: xxx
526}
527
528void Android_ShowKeyboard()
529{
530	ftk_logd("Android_ShowKeyboard()");
531	jni.env->CallStaticVoidMethod(jni.activity, jni.show_keyboard);
532}
533
534void Android_HideKeyboard()
535{
536	ftk_logd("Android_HideKeyboard()");
537	jni.env->CallStaticVoidMethod(jni.activity, jni.hide_keyboard);
538}
539
540void Android_ShowInputMethodChooser()
541{
542	ftk_logd("Android_ShowInputMethodChooser()");
543	jni.env->CallStaticVoidMethod(jni.activity, jni.show_input_method_picker);
544}