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