// // Lol Engine // // Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net> // // Lol Engine is free software. It comes without any warranty, to // the extent permitted by applicable law. You can redistribute it // and/or modify it under the terms of the Do What the Fuck You Want // to Public License, Version 2, as published by the WTFPL Task Force. // See http://www.wtfpl.net/ for more details. // #include <lol/engine-internal.h> #if defined __ANDROID__ #include <jni.h> #include <android/log.h> extern "C" { #include <android_native_app_glue.h> } #include "../../image/resource-private.h" namespace lol { extern ANativeActivity *g_activity; /* * Image implementation class */ class AndroidImageCodec : public ResourceCodec { public: virtual char const *GetName() { return "<AndroidImageCodec>"; } virtual ResourceCodecData* Load(char const *path); virtual bool Save(char const *path, ResourceCodecData* data); virtual bool Close(); virtual uint8_t *GetData() const; private: jobject m_bmp; jintArray m_array; jint *m_pixels; }; DECLARE_IMAGE_CODEC(AndroidImageCodec, 100) ResourceCodecData* AndroidImageCodec::Load(char const *path) { JNIEnv *env; jint res = g_activity->vm->GetEnv((void **)&env, JNI_VERSION_1_2); if (res < 0) { #if !LOL_BUILD_RELEASE msg::error("JVM environment not found, trying to attach thread\n"); #endif res = g_activity->vm->AttachCurrentThread(&env, nullptr); } if (res < 0) { #if !LOL_BUILD_RELEASE msg::error("JVM environment not found, cannot open image %s\n", path); #endif return false; } jclass cls = env->GetObjectClass(g_activity->clazz); jmethodID mid; mid = env->GetMethodID(cls, "openImage", "(Ljava/lang/String;)Landroid/graphics/Bitmap;"); jstring name = env->NewStringUTF(path); m_bmp = env->CallObjectMethod(g_activity->clazz, mid, name); env->DeleteLocalRef(name); if (!m_bmp) { #if !LOL_BUILD_RELEASE msg::error("could not load %s\n", path); #endif return false; } env->NewGlobalRef(m_bmp); /* Get image dimensions */ mid = env->GetMethodID(cls, "getWidth", "(Landroid/graphics/Bitmap;)I"); m_size.x = env->CallIntMethod(g_activity->clazz, mid, m_bmp); mid = env->GetMethodID(cls, "getHeight", "(Landroid/graphics/Bitmap;)I"); m_size.y = env->CallIntMethod(g_activity->clazz, mid, m_bmp); /* Get pixels */ m_array = env->NewIntArray(m_size.x * m_size.y); env->NewGlobalRef(m_array); mid = env->GetMethodID(cls, "getPixels", "(Landroid/graphics/Bitmap;[I)V"); env->CallVoidMethod(g_activity->clazz, mid, m_bmp, m_array); m_pixels = env->GetIntArrayElements(m_array, 0); for (int n = 0; n < m_size.x * m_size.y; n++) { uint32_t u = m_pixels[n]; u = (u & 0xff00ff00) | ((u & 0xff0000) >> 16) | ((u & 0xff) << 16); m_pixels[n] = u; } m_format = PixelFormat::RGBA_8; return new ResourceCodecData(); } bool AndroidImageCodec::Save(char const *path, ResourceCodecData* data) { UNUSED(path, data); /* TODO: unimplemented */ } bool AndroidImageCodec::Close() { JNIEnv *env; jint res = g_activity->vm->GetEnv((void **)&env, JNI_VERSION_1_2); if (res < 0) { #if !LOL_BUILD_RELEASE msg::error("JVM environment not found, cannot close image\n"); #endif return false; } jclass cls = env->GetObjectClass(g_activity->clazz); jmethodID mid; env->ReleaseIntArrayElements(m_array, m_pixels, 0); env->DeleteGlobalRef(m_array); /* Free image */ mid = env->GetMethodID(cls, "closeImage", "(Landroid/graphics/Bitmap;)V"); env->CallVoidMethod(g_activity->clazz, mid, m_bmp); env->DeleteGlobalRef(m_bmp); return true; } uint8_t *AndroidImageCodec::GetData() const { return (uint8_t *)m_pixels; } } /* namespace lol */ #endif /* __ANDROID__ */