153 lines
3.9 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net>
  5. //
  6. // Lol Engine is free software. It comes without any warranty, to
  7. // the extent permitted by applicable law. You can redistribute it
  8. // and/or modify it under the terms of the Do What the Fuck You Want
  9. // to Public License, Version 2, as published by the WTFPL Task Force.
  10. // See http://www.wtfpl.net/ for more details.
  11. //
  12. #include <lol/engine-internal.h>
  13. #if defined __ANDROID__
  14. #include <jni.h>
  15. #include <android/log.h>
  16. extern "C" {
  17. #include <android_native_app_glue.h>
  18. }
  19. #include "../../image/resource-private.h"
  20. namespace lol
  21. {
  22. extern ANativeActivity *g_activity;
  23. /*
  24. * Image implementation class
  25. */
  26. class AndroidImageCodec : public ResourceCodec
  27. {
  28. public:
  29. virtual char const *GetName() { return "<AndroidImageCodec>"; }
  30. virtual ResourceCodecData* Load(char const *path);
  31. virtual bool Save(char const *path, ResourceCodecData* data);
  32. virtual bool Close();
  33. virtual uint8_t *GetData() const;
  34. private:
  35. jobject m_bmp;
  36. jintArray m_array;
  37. jint *m_pixels;
  38. };
  39. DECLARE_IMAGE_CODEC(AndroidImageCodec, 100)
  40. ResourceCodecData* AndroidImageCodec::Load(char const *path)
  41. {
  42. JNIEnv *env;
  43. jint res = g_activity->vm->GetEnv((void **)&env, JNI_VERSION_1_2);
  44. if (res < 0)
  45. {
  46. #if !LOL_BUILD_RELEASE
  47. msg::error("JVM environment not found, trying to attach thread\n");
  48. #endif
  49. res = g_activity->vm->AttachCurrentThread(&env, nullptr);
  50. }
  51. if (res < 0)
  52. {
  53. #if !LOL_BUILD_RELEASE
  54. msg::error("JVM environment not found, cannot open image %s\n", path);
  55. #endif
  56. return false;
  57. }
  58. jclass cls = env->GetObjectClass(g_activity->clazz);
  59. jmethodID mid;
  60. mid = env->GetMethodID(cls, "openImage",
  61. "(Ljava/lang/String;)Landroid/graphics/Bitmap;");
  62. jstring name = env->NewStringUTF(path);
  63. m_bmp = env->CallObjectMethod(g_activity->clazz, mid, name);
  64. env->DeleteLocalRef(name);
  65. if (!m_bmp)
  66. {
  67. #if !LOL_BUILD_RELEASE
  68. msg::error("could not load %s\n", path);
  69. #endif
  70. return false;
  71. }
  72. env->NewGlobalRef(m_bmp);
  73. /* Get image dimensions */
  74. mid = env->GetMethodID(cls, "getWidth", "(Landroid/graphics/Bitmap;)I");
  75. m_size.x = env->CallIntMethod(g_activity->clazz, mid, m_bmp);
  76. mid = env->GetMethodID(cls, "getHeight", "(Landroid/graphics/Bitmap;)I");
  77. m_size.y = env->CallIntMethod(g_activity->clazz, mid, m_bmp);
  78. /* Get pixels */
  79. m_array = env->NewIntArray(m_size.x * m_size.y);
  80. env->NewGlobalRef(m_array);
  81. mid = env->GetMethodID(cls, "getPixels", "(Landroid/graphics/Bitmap;[I)V");
  82. env->CallVoidMethod(g_activity->clazz, mid, m_bmp, m_array);
  83. m_pixels = env->GetIntArrayElements(m_array, 0);
  84. for (int n = 0; n < m_size.x * m_size.y; n++)
  85. {
  86. uint32_t u = m_pixels[n];
  87. u = (u & 0xff00ff00) | ((u & 0xff0000) >> 16) | ((u & 0xff) << 16);
  88. m_pixels[n] = u;
  89. }
  90. m_format = PixelFormat::RGBA_8;
  91. return new ResourceCodecData();
  92. }
  93. bool AndroidImageCodec::Save(char const *path, ResourceCodecData* data)
  94. {
  95. UNUSED(path, data);
  96. /* TODO: unimplemented */
  97. }
  98. bool AndroidImageCodec::Close()
  99. {
  100. JNIEnv *env;
  101. jint res = g_activity->vm->GetEnv((void **)&env, JNI_VERSION_1_2);
  102. if (res < 0)
  103. {
  104. #if !LOL_BUILD_RELEASE
  105. msg::error("JVM environment not found, cannot close image\n");
  106. #endif
  107. return false;
  108. }
  109. jclass cls = env->GetObjectClass(g_activity->clazz);
  110. jmethodID mid;
  111. env->ReleaseIntArrayElements(m_array, m_pixels, 0);
  112. env->DeleteGlobalRef(m_array);
  113. /* Free image */
  114. mid = env->GetMethodID(cls, "closeImage", "(Landroid/graphics/Bitmap;)V");
  115. env->CallVoidMethod(g_activity->clazz, mid, m_bmp);
  116. env->DeleteGlobalRef(m_bmp);
  117. return true;
  118. }
  119. uint8_t *AndroidImageCodec::GetData() const
  120. {
  121. return (uint8_t *)m_pixels;
  122. }
  123. } /* namespace lol */
  124. #endif /* __ANDROID__ */