| @@ -1045,6 +1045,7 @@ | |||
| 59C46E289F86C80D4341EAA3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Files.cpp"; path = "../../src/native/android/juce_android_Files.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| FA82460758BDCB2DCCE1EAAA = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Fonts.cpp"; path = "../../src/native/android/juce_android_Fonts.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| CE06EEED7426AA45C27B629C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_GraphicsContext.cpp"; path = "../../src/native/android/juce_android_GraphicsContext.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| F439E6C4B2D2AF19645252C0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_android_JNIHelpers.h"; path = "../../src/native/android/juce_android_JNIHelpers.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| 1D74C9567283836ECC70E48B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Messaging.cpp"; path = "../../src/native/android/juce_android_Messaging.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| 40216CE846A54CE706131A23 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Midi.cpp"; path = "../../src/native/android/juce_android_Midi.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| E646726910F110DC34DD1662 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Misc.cpp"; path = "../../src/native/android/juce_android_Misc.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| @@ -1889,6 +1890,7 @@ | |||
| 59C46E289F86C80D4341EAA3, | |||
| FA82460758BDCB2DCCE1EAAA, | |||
| CE06EEED7426AA45C27B629C, | |||
| F439E6C4B2D2AF19645252C0, | |||
| 1D74C9567283836ECC70E48B, | |||
| 40216CE846A54CE706131A23, | |||
| E646726910F110DC34DD1662, | |||
| @@ -951,6 +951,7 @@ | |||
| <File RelativePath="..\..\src\native\android\juce_android_Files.cpp"/> | |||
| <File RelativePath="..\..\src\native\android\juce_android_Fonts.cpp"/> | |||
| <File RelativePath="..\..\src\native\android\juce_android_GraphicsContext.cpp"/> | |||
| <File RelativePath="..\..\src\native\android\juce_android_JNIHelpers.h"/> | |||
| <File RelativePath="..\..\src\native\android\juce_android_Messaging.cpp"/> | |||
| <File RelativePath="..\..\src\native\android\juce_android_Midi.cpp"/> | |||
| <File RelativePath="..\..\src\native\android\juce_android_Misc.cpp"/> | |||
| @@ -951,6 +951,7 @@ | |||
| <File RelativePath="..\..\src\native\android\juce_android_Files.cpp"/> | |||
| <File RelativePath="..\..\src\native\android\juce_android_Fonts.cpp"/> | |||
| <File RelativePath="..\..\src\native\android\juce_android_GraphicsContext.cpp"/> | |||
| <File RelativePath="..\..\src\native\android\juce_android_JNIHelpers.h"/> | |||
| <File RelativePath="..\..\src\native\android\juce_android_Messaging.cpp"/> | |||
| <File RelativePath="..\..\src\native\android\juce_android_Midi.cpp"/> | |||
| <File RelativePath="..\..\src\native\android\juce_android_Misc.cpp"/> | |||
| @@ -953,6 +953,7 @@ | |||
| <File RelativePath="..\..\src\native\android\juce_android_Files.cpp"/> | |||
| <File RelativePath="..\..\src\native\android\juce_android_Fonts.cpp"/> | |||
| <File RelativePath="..\..\src\native\android\juce_android_GraphicsContext.cpp"/> | |||
| <File RelativePath="..\..\src\native\android\juce_android_JNIHelpers.h"/> | |||
| <File RelativePath="..\..\src\native\android\juce_android_Messaging.cpp"/> | |||
| <File RelativePath="..\..\src\native\android\juce_android_Midi.cpp"/> | |||
| <File RelativePath="..\..\src\native\android\juce_android_Misc.cpp"/> | |||
| @@ -794,6 +794,7 @@ | |||
| <ClInclude Include="..\..\src\native\windows\juce_win32_ComSmartPtr.h"/> | |||
| <ClInclude Include="..\..\src\native\windows\juce_win32_HiddenMessageWindow.h"/> | |||
| <ClInclude Include="..\..\src\native\windows\juce_win32_NativeIncludes.h"/> | |||
| <ClInclude Include="..\..\src\native\android\juce_android_JNIHelpers.h"/> | |||
| <ClInclude Include="..\..\src\native\android\juce_android_NativeIncludes.h"/> | |||
| <ClInclude Include="..\..\src\text\juce_CharacterFunctions.h"/> | |||
| <ClInclude Include="..\..\src\text\juce_CharPointer_ASCII.h"/> | |||
| @@ -2313,6 +2313,9 @@ | |||
| <ClInclude Include="..\..\src\native\windows\juce_win32_NativeIncludes.h"> | |||
| <Filter>Juce\Source\native\windows</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\src\native\android\juce_android_JNIHelpers.h"> | |||
| <Filter>Juce\Source\native\android</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\src\native\android\juce_android_NativeIncludes.h"> | |||
| <Filter>Juce\Source\native\android</Filter> | |||
| </ClInclude> | |||
| @@ -1045,6 +1045,7 @@ | |||
| 59C46E289F86C80D4341EAA3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Files.cpp"; path = "../../src/native/android/juce_android_Files.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| FA82460758BDCB2DCCE1EAAA = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Fonts.cpp"; path = "../../src/native/android/juce_android_Fonts.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| CE06EEED7426AA45C27B629C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_GraphicsContext.cpp"; path = "../../src/native/android/juce_android_GraphicsContext.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| F439E6C4B2D2AF19645252C0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_android_JNIHelpers.h"; path = "../../src/native/android/juce_android_JNIHelpers.h"; sourceTree = "SOURCE_ROOT"; }; | |||
| 1D74C9567283836ECC70E48B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Messaging.cpp"; path = "../../src/native/android/juce_android_Messaging.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| 40216CE846A54CE706131A23 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Midi.cpp"; path = "../../src/native/android/juce_android_Midi.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| E646726910F110DC34DD1662 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_android_Misc.cpp"; path = "../../src/native/android/juce_android_Misc.cpp"; sourceTree = "SOURCE_ROOT"; }; | |||
| @@ -1889,6 +1890,7 @@ | |||
| 59C46E289F86C80D4341EAA3, | |||
| FA82460758BDCB2DCCE1EAAA, | |||
| CE06EEED7426AA45C27B629C, | |||
| F439E6C4B2D2AF19645252C0, | |||
| 1D74C9567283836ECC70E48B, | |||
| 40216CE846A54CE706131A23, | |||
| E646726910F110DC34DD1662, | |||
| @@ -1478,6 +1478,8 @@ | |||
| file="src/native/android/juce_android_Fonts.cpp"/> | |||
| <FILE id="VFjwst" name="juce_android_GraphicsContext.cpp" compile="1" | |||
| resource="0" file="src/native/android/juce_android_GraphicsContext.cpp"/> | |||
| <FILE id="HolDOi" name="juce_android_JNIHelpers.h" compile="0" resource="0" | |||
| file="src/native/android/juce_android_JNIHelpers.h"/> | |||
| <FILE id="TV84om" name="juce_android_Messaging.cpp" compile="1" resource="0" | |||
| file="src/native/android/juce_android_Messaging.cpp"/> | |||
| <FILE id="mJh1wV" name="juce_android_Midi.cpp" compile="1" resource="0" | |||
| @@ -27,6 +27,32 @@ | |||
| // compiled on its own). | |||
| #if JUCE_INCLUDED_FILE | |||
| //============================================================================== | |||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| STATICMETHOD (getMinBufferSize, "getMinBufferSize", "(III)I") \ | |||
| STATICMETHOD (getNativeOutputSampleRate, "getNativeOutputSampleRate", "(I)I") \ | |||
| METHOD (constructor, "<init>", "(IIIIII)V") \ | |||
| METHOD (play, "play", "()V") \ | |||
| METHOD (stop, "stop", "()V") \ | |||
| METHOD (release, "release", "()V") \ | |||
| METHOD (flush, "flush", "()V") \ | |||
| METHOD (write, "write", "([SII)I") \ | |||
| DECLARE_JNI_CLASS (AudioTrack, "android/media/AudioTrack"); | |||
| #undef JNI_CLASS_MEMBERS | |||
| //============================================================================== | |||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| STATICMETHOD (getMinBufferSize, "getMinBufferSize", "(III)I") \ | |||
| METHOD (constructor, "<init>", "(IIIII)V"); \ | |||
| METHOD (startRecording, "startRecording", "()V"); \ | |||
| METHOD (stop, "stop", "()V"); \ | |||
| METHOD (read, "read", "([SII)I"); \ | |||
| METHOD (release, "release", "()V"); \ | |||
| DECLARE_JNI_CLASS (AudioRecord, "android/media/AudioRecord"); | |||
| #undef JNI_CLASS_MEMBERS | |||
| //============================================================================== | |||
| #define CHANNEL_OUT_STEREO ((jint) 12) | |||
| #define CHANNEL_IN_STEREO ((jint) 12) | |||
| @@ -53,14 +79,14 @@ public: | |||
| inputChannelBuffer (1, 1) | |||
| { | |||
| JNIEnv* env = getEnv(); | |||
| sampleRate = env->CallStaticIntMethod (android.audioTrackClass, android.getNativeOutputSampleRate, MODE_STREAM); | |||
| sampleRate = env->CallStaticIntMethod (AudioTrack, AudioTrack.getNativeOutputSampleRate, MODE_STREAM); | |||
| const jint outMinBuffer = env->CallStaticIntMethod (android.audioTrackClass, android.getMinBufferSize, sampleRate, CHANNEL_OUT_STEREO, ENCODING_PCM_16BIT); | |||
| const jint outMinBuffer = env->CallStaticIntMethod (AudioTrack, AudioTrack.getMinBufferSize, sampleRate, CHANNEL_OUT_STEREO, ENCODING_PCM_16BIT); | |||
| jint inMinBuffer = env->CallStaticIntMethod (android.audioRecordClass, android.getMinRecordBufferSize, sampleRate, CHANNEL_IN_STEREO, ENCODING_PCM_16BIT); | |||
| jint inMinBuffer = env->CallStaticIntMethod (AudioRecord, AudioRecord.getMinBufferSize, sampleRate, CHANNEL_IN_STEREO, ENCODING_PCM_16BIT); | |||
| if (inMinBuffer <= 0) | |||
| { | |||
| inMinBuffer = env->CallStaticIntMethod (android.audioRecordClass, android.getMinRecordBufferSize, sampleRate, CHANNEL_IN_MONO, ENCODING_PCM_16BIT); | |||
| inMinBuffer = env->CallStaticIntMethod (AudioRecord, AudioRecord.getMinBufferSize, sampleRate, CHANNEL_IN_MONO, ENCODING_PCM_16BIT); | |||
| if (inMinBuffer > 0) | |||
| numDeviceInputChannelsAvailable = 1; | |||
| @@ -146,7 +172,7 @@ public: | |||
| if (numClientOutputChannels > 0) | |||
| { | |||
| numDeviceOutputChannels = 2; | |||
| outputDevice = GlobalRef (env->NewObject (android.audioTrackClass, android.audioTrackConstructor, | |||
| outputDevice = GlobalRef (env->NewObject (AudioTrack, AudioTrack.constructor, | |||
| STREAM_MUSIC, sampleRate, CHANNEL_OUT_STEREO, ENCODING_PCM_16BIT, | |||
| (jint) (actualBufferSize * numDeviceOutputChannels * sizeof (float)), MODE_STREAM)); | |||
| isRunning = true; | |||
| @@ -155,7 +181,7 @@ public: | |||
| if (numClientInputChannels > 0 && numDeviceInputChannelsAvailable > 0) | |||
| { | |||
| numDeviceInputChannels = jmin (numClientInputChannels, numDeviceInputChannelsAvailable); | |||
| inputDevice = GlobalRef (env->NewObject (android.audioRecordClass, android.audioRecordConstructor, | |||
| inputDevice = GlobalRef (env->NewObject (AudioRecord, AudioRecord.constructor, | |||
| 0 /* (default audio source) */, sampleRate, | |||
| numDeviceInputChannelsAvailable > 1 ? CHANNEL_IN_STEREO : CHANNEL_IN_MONO, | |||
| ENCODING_PCM_16BIT, | |||
| @@ -166,10 +192,10 @@ public: | |||
| if (isRunning) | |||
| { | |||
| if (outputDevice != nullptr) | |||
| env->CallVoidMethod (outputDevice, android.audioTrackPlay); | |||
| env->CallVoidMethod (outputDevice, AudioTrack.play); | |||
| if (inputDevice != nullptr) | |||
| env->CallVoidMethod (inputDevice, android.startRecording); | |||
| env->CallVoidMethod (inputDevice, AudioRecord.startRecording); | |||
| startThread (8); | |||
| } | |||
| @@ -240,7 +266,7 @@ public: | |||
| { | |||
| if (inputDevice != nullptr) | |||
| { | |||
| jint numRead = env->CallIntMethod (inputDevice, android.audioRecordRead, audioBuffer, 0, actualBufferSize * numDeviceInputChannels); | |||
| jint numRead = env->CallIntMethod (inputDevice, AudioRecord.read, audioBuffer, 0, actualBufferSize * numDeviceInputChannels); | |||
| if (numRead < actualBufferSize * numDeviceInputChannels) | |||
| { | |||
| @@ -292,7 +318,7 @@ public: | |||
| } | |||
| env->ReleaseShortArrayElements (audioBuffer, dest, 0); | |||
| jint numWritten = env->CallIntMethod (outputDevice, android.audioTrackWrite, audioBuffer, 0, actualBufferSize * numDeviceOutputChannels); | |||
| jint numWritten = env->CallIntMethod (outputDevice, AudioTrack.write, audioBuffer, 0, actualBufferSize * numDeviceOutputChannels); | |||
| if (numWritten < actualBufferSize * numDeviceOutputChannels) | |||
| { | |||
| @@ -320,15 +346,15 @@ private: | |||
| { | |||
| if (outputDevice != nullptr) | |||
| { | |||
| outputDevice.callVoidMethod (android.audioTrackStop); | |||
| outputDevice.callVoidMethod (android.audioTrackRelease); | |||
| outputDevice.callVoidMethod (AudioTrack.stop); | |||
| outputDevice.callVoidMethod (AudioTrack.release); | |||
| outputDevice.clear(); | |||
| } | |||
| if (inputDevice != nullptr) | |||
| { | |||
| inputDevice.callVoidMethod (android.stopRecording); | |||
| inputDevice.callVoidMethod (android.audioRecordRelease); | |||
| inputDevice.callVoidMethod (AudioRecord.stop); | |||
| inputDevice.callVoidMethod (AudioRecord.release); | |||
| inputDevice.clear(); | |||
| } | |||
| } | |||
| @@ -27,6 +27,14 @@ | |||
| // compiled on its own). | |||
| #if JUCE_INCLUDED_FILE | |||
| //============================================================================== | |||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| STATICMETHOD (create, "create", "(Ljava/lang/String;I)Landroid/graphics/Typeface;") \ | |||
| STATICMETHOD (createFromFile, "createFromFile", "(Ljava/lang/String;)Landroid/graphics/Typeface;") \ | |||
| DECLARE_JNI_CLASS (TypefaceClass, "android/graphics/Typeface"); | |||
| #undef JNI_CLASS_MEMBERS | |||
| //============================================================================== | |||
| StringArray Font::findAllTypefaceNames() | |||
| @@ -68,21 +76,21 @@ public: | |||
| File fontFile (File ("/system/fonts").getChildFile (name).withFileExtension (".ttf")); | |||
| if (fontFile.exists()) | |||
| typeface = GlobalRef (env->CallStaticObjectMethod (android.typefaceClass, android.createFromFile, | |||
| typeface = GlobalRef (env->CallStaticObjectMethod (TypefaceClass, TypefaceClass.createFromFile, | |||
| javaString (fontFile.getFullPathName()).get())); | |||
| else | |||
| typeface = GlobalRef (env->CallStaticObjectMethod (android.typefaceClass, android.create, | |||
| typeface = GlobalRef (env->CallStaticObjectMethod (TypefaceClass, TypefaceClass.create, | |||
| javaString (getName()).get(), flags)); | |||
| rect = GlobalRef (env->NewObject (android.rectClass, android.rectConstructor, 0, 0, 0, 0)); | |||
| rect = GlobalRef (env->NewObject (RectClass, RectClass.constructor, 0, 0, 0, 0)); | |||
| paint = GlobalRef (android.createPaint (Graphics::highResamplingQuality)); | |||
| const LocalRef<jobject> ignored (paint.callObjectMethod (android.setTypeface, typeface.get())); | |||
| const LocalRef<jobject> ignored (paint.callObjectMethod (Paint.setTypeface, typeface.get())); | |||
| const float standardSize = 256.0f; | |||
| paint.callVoidMethod (android.setTextSize, standardSize); | |||
| ascent = std::abs (paint.callFloatMethod (android.ascent)) / standardSize; | |||
| descent = paint.callFloatMethod (android.descent) / standardSize; | |||
| paint.callVoidMethod (Paint.setTextSize, standardSize); | |||
| ascent = std::abs (paint.callFloatMethod (Paint.ascent)) / standardSize; | |||
| descent = paint.callFloatMethod (Paint.descent) / standardSize; | |||
| const float height = ascent + descent; | |||
| unitsToHeightScaleFactor = 1.0f / 256.0f;//(height * standardSize); | |||
| @@ -97,7 +105,7 @@ public: | |||
| const int numChars = text.length(); | |||
| jfloatArray widths = env->NewFloatArray (numChars); | |||
| const int numDone = paint.callIntMethod (android.getTextWidths, javaString (text).get(), widths); | |||
| const int numDone = paint.callIntMethod (Paint.getTextWidths, javaString (text).get(), widths); | |||
| HeapBlock<jfloat> localWidths (numDone); | |||
| env->GetFloatArrayRegion (widths, 0, numDone, localWidths); | |||
| @@ -116,7 +124,7 @@ public: | |||
| const int numChars = text.length(); | |||
| jfloatArray widths = env->NewFloatArray (numChars); | |||
| const int numDone = paint.callIntMethod (android.getTextWidths, javaString (text).get(), widths); | |||
| const int numDone = paint.callIntMethod (Paint.getTextWidths, javaString (text).get(), widths); | |||
| HeapBlock<jfloat> localWidths (numDone); | |||
| env->GetFloatArrayRegion (widths, 0, numDone, localWidths); | |||
| @@ -145,14 +153,14 @@ public: | |||
| JNIEnv* env = getEnv(); | |||
| jobject matrix = android.createMatrix (env, AffineTransform::scale (unitsToHeightScaleFactor, unitsToHeightScaleFactor).followedBy (t)); | |||
| jintArray maskData = (jintArray) android.activity.callObjectMethod (android.renderGlyph, (jchar) glyphNumber, paint.get(), matrix, rect.get()); | |||
| jintArray maskData = (jintArray) android.activity.callObjectMethod (JuceAppActivity.renderGlyph, (jchar) glyphNumber, paint.get(), matrix, rect.get()); | |||
| env->DeleteLocalRef (matrix); | |||
| const int left = env->GetIntField (rect.get(), android.rectLeft); | |||
| const int top = env->GetIntField (rect.get(), android.rectTop); | |||
| const int right = env->GetIntField (rect.get(), android.rectRight); | |||
| const int bottom = env->GetIntField (rect.get(), android.rectBottom); | |||
| const int left = env->GetIntField (rect.get(), RectClass.left); | |||
| const int top = env->GetIntField (rect.get(), RectClass.top); | |||
| const int right = env->GetIntField (rect.get(), RectClass.right); | |||
| const int bottom = env->GetIntField (rect.get(), RectClass.bottom); | |||
| const Rectangle<int> bounds (left, top, right - left, bottom - top); | |||
| @@ -28,6 +28,107 @@ | |||
| #if JUCE_INCLUDED_FILE | |||
| #if USE_ANDROID_CANVAS | |||
| //============================================================================== | |||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| METHOD (constructor, "<init>", "(Landroid/graphics/Bitmap;)V") \ | |||
| METHOD (drawRect, "drawRect", "(FFFFLandroid/graphics/Paint;)V") \ | |||
| METHOD (translate, "translate", "(FF)V") \ | |||
| METHOD (clipPath, "clipPath", "(Landroid/graphics/Path;)Z") \ | |||
| METHOD (clipRect, "clipRect", "(FFFF)Z") \ | |||
| METHOD (clipRegion, "clipRegion", "(Landroid/graphics/Region;)Z") \ | |||
| METHOD (concat, "concat", "(Landroid/graphics/Matrix;)V") \ | |||
| METHOD (drawBitmap, "drawBitmap", "(Landroid/graphics/Bitmap;Landroid/graphics/Matrix;Landroid/graphics/Paint;)V") \ | |||
| METHOD (drawBitmapAt, "drawBitmap", "(Landroid/graphics/Bitmap;FFLandroid/graphics/Paint;)V") \ | |||
| METHOD (drawMemoryBitmap, "drawBitmap", "([IIIFFIIZLandroid/graphics/Paint;)V") \ | |||
| METHOD (drawLine, "drawLine", "(FFFFLandroid/graphics/Paint;)V") \ | |||
| METHOD (drawPath, "drawPath", "(Landroid/graphics/Path;Landroid/graphics/Paint;)V") \ | |||
| METHOD (drawText, "drawText", "(Ljava/lang/String;FFLandroid/graphics/Paint;)V") \ | |||
| METHOD (getClipBounds, "getClipBounds", "(Landroid/graphics/Rect;)Z") \ | |||
| METHOD (getClipBounds2, "getClipBounds", "()Landroid/graphics/Rect;") \ | |||
| METHOD (getMatrix, "getMatrix", "()Landroid/graphics/Matrix;") \ | |||
| METHOD (save, "save", "()I") \ | |||
| METHOD (restore, "restore", "()V") \ | |||
| METHOD (saveLayerAlpha, "saveLayerAlpha", "(FFFFII)I") | |||
| DECLARE_JNI_CLASS (Canvas, "android/graphics/Canvas"); | |||
| #undef JNI_CLASS_MEMBERS | |||
| //============================================================================== | |||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| METHOD (constructor, "<init>", "()V") \ | |||
| METHOD (moveTo, "moveTo", "(FF)V") \ | |||
| METHOD (lineTo, "lineTo", "(FF)V") \ | |||
| METHOD (quadTo, "quadTo", "(FFFF)V") \ | |||
| METHOD (cubicTo, "cubicTo", "(FFFFFF)V") \ | |||
| METHOD (closePath, "close", "()V") \ | |||
| METHOD (computeBounds, "computeBounds", "(Landroid/graphics/RectF;Z)V") \ | |||
| DECLARE_JNI_CLASS (PathClass, "android/graphics/Path"); | |||
| #undef JNI_CLASS_MEMBERS | |||
| //============================================================================== | |||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| METHOD (constructor, "<init>", "()V"); \ | |||
| METHOD (regionUnion, "union", "(Landroid/graphics/Rect;)Z"); \ | |||
| DECLARE_JNI_CLASS (RegionClass, "android/graphics/Region"); | |||
| #undef JNI_CLASS_MEMBERS | |||
| //============================================================================== | |||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| STATICMETHOD (createBitmap, "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;") \ | |||
| METHOD (bitmapCopy, "copy", "(Landroid/graphics/Bitmap$Config;Z)Landroid/graphics/Bitmap;") \ | |||
| METHOD (getPixels, "getPixels", "([IIIIIII)V") \ | |||
| METHOD (setPixels, "setPixels", "([IIIIIII)V") \ | |||
| METHOD (recycle, "recycle", "()V") \ | |||
| DECLARE_JNI_CLASS (BitmapClass, "android/graphics/Bitmap"); | |||
| #undef JNI_CLASS_MEMBERS | |||
| //============================================================================== | |||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| STATICFIELD (ARGB_8888, "ARGB_8888", "Landroid/graphics/Bitmap$Config;") \ | |||
| STATICFIELD (ALPHA_8, "ALPHA_8", "Landroid/graphics/Bitmap$Config;") \ | |||
| DECLARE_JNI_CLASS (BitmapConfig, "android/graphics/Bitmap$Config"); | |||
| #undef JNI_CLASS_MEMBERS | |||
| //============================================================================== | |||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| METHOD (constructor, "<init>", "(Landroid/graphics/Bitmap;Landroid/graphics/Shader$TileMode;Landroid/graphics/Shader$TileMode;)V") | |||
| DECLARE_JNI_CLASS (BitmapShader, "android/graphics/BitmapShader"); | |||
| #undef JNI_CLASS_MEMBERS | |||
| //============================================================================== | |||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| METHOD (setLocalMatrix, "setLocalMatrix", "(Landroid/graphics/Matrix;)V") | |||
| DECLARE_JNI_CLASS (ShaderClass, "android/graphics/Shader"); | |||
| #undef JNI_CLASS_MEMBERS | |||
| //============================================================================== | |||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| STATICFIELD (CLAMP, "CLAMP", "Landroid/graphics/Shader$TileMode;") | |||
| DECLARE_JNI_CLASS (ShaderTileMode, "android/graphics/Shader$TileMode"); | |||
| #undef JNI_CLASS_MEMBERS | |||
| //============================================================================== | |||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| METHOD (constructor, "<init>", "(FFFF[I[FLandroid/graphics/Shader$TileMode;)V") \ | |||
| DECLARE_JNI_CLASS (LinearGradientClass, "android/graphics/LinearGradient"); | |||
| #undef JNI_CLASS_MEMBERS | |||
| //============================================================================== | |||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| METHOD (constructor, "<init>", "(FFF[I[FLandroid/graphics/Shader$TileMode;)V") \ | |||
| DECLARE_JNI_CLASS (RadialGradientClass, "android/graphics/RadialGradient"); | |||
| #undef JNI_CLASS_MEMBERS | |||
| //============================================================================== | |||
| class AndroidImage : public Image::SharedImage | |||
| { | |||
| @@ -48,7 +149,7 @@ public: | |||
| ~AndroidImage() | |||
| { | |||
| if (bitmap != 0) | |||
| bitmap.callVoidMethod (android.recycle); | |||
| bitmap.callVoidMethod (BitmapClass.recycle); | |||
| } | |||
| Image::ImageType getType() const { return Image::NativeImage; } | |||
| @@ -65,8 +166,8 @@ public: | |||
| SharedImage* clone() | |||
| { | |||
| JNIEnv* env = getEnv(); | |||
| jobject mode = env->GetStaticObjectField (android.bitmapConfigClass, android.ARGB_8888); | |||
| GlobalRef newCopy (bitmap.callObjectMethod (android.bitmapCopy, mode, true)); | |||
| jobject mode = env->GetStaticObjectField (BitmapConfig, BitmapConfig.ARGB_8888); | |||
| GlobalRef newCopy (bitmap.callObjectMethod (BitmapClass.bitmapCopy, mode, true)); | |||
| env->DeleteLocalRef (mode); | |||
| return new AndroidImage (width, height, newCopy); | |||
| @@ -75,8 +176,9 @@ public: | |||
| static jobject createBitmap (int width, int height, bool asSingleChannel) | |||
| { | |||
| JNIEnv* env = getEnv(); | |||
| jobject mode = env->GetStaticObjectField (android.bitmapConfigClass, asSingleChannel ? android.ALPHA_8 : android.ARGB_8888); | |||
| jobject result = env->CallStaticObjectMethod (android.bitmapClass, android.createBitmap, width, height, mode); | |||
| jobject mode = env->GetStaticObjectField (BitmapConfig, asSingleChannel ? BitmapConfig.ALPHA_8 | |||
| : BitmapConfig.ARGB_8888); | |||
| jobject result = env->CallStaticObjectMethod (BitmapClass, BitmapClass.createBitmap, width, height, mode); | |||
| env->DeleteLocalRef (mode); | |||
| return result; | |||
| } | |||
| @@ -97,7 +199,7 @@ private: | |||
| intArray = env->NewIntArray (bitmapData.width * bitmapData.height); | |||
| if (mode != Image::BitmapData::writeOnly) | |||
| owner_.bitmap.callVoidMethod (android.getPixels, intArray, 0, bitmapData.width, x_, y_, | |||
| owner_.bitmap.callVoidMethod (BitmapClass.getPixels, intArray, 0, bitmapData.width, x_, y_, | |||
| bitmapData.width, bitmapData.height); | |||
| bitmapData.data = (uint8*) env->GetIntArrayElements (intArray, 0); | |||
| @@ -132,7 +234,7 @@ private: | |||
| env->ReleaseIntArrayElements (intArray, (jint*) bitmapData.data, 0); | |||
| if (mode != Image::BitmapData::readOnly) | |||
| owner.bitmap.callVoidMethod (android.setPixels, intArray, 0, bitmapData.width, x, y, | |||
| owner.bitmap.callVoidMethod (BitmapClass.setPixels, intArray, 0, bitmapData.width, x, y, | |||
| bitmapData.width, bitmapData.height); | |||
| env->DeleteLocalRef (intArray); | |||
| @@ -187,12 +289,12 @@ public: | |||
| //============================================================================== | |||
| void setOrigin (int x, int y) | |||
| { | |||
| getCanvas().callVoidMethod (android.translate, (float) x, (float) y); | |||
| getCanvas().callVoidMethod (Canvas.translate, (float) x, (float) y); | |||
| } | |||
| void addTransform (const AffineTransform& transform) | |||
| { | |||
| getCanvas().callVoidMethod (android.concat, createMatrixRef (getEnv(), transform).get()); | |||
| getCanvas().callVoidMethod (Canvas.concat, createMatrixRef (getEnv(), transform).get()); | |||
| } | |||
| float getScaleFactor() | |||
| @@ -202,7 +304,7 @@ public: | |||
| bool clipToRectangle (const Rectangle<int>& r) | |||
| { | |||
| return getCanvas().callBooleanMethod (android.clipRect, (float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom()); | |||
| return getCanvas().callBooleanMethod (Canvas.clipRect, (float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom()); | |||
| } | |||
| bool clipToRectangleList (const RectangleList& clipRegion) | |||
| @@ -218,13 +320,13 @@ public: | |||
| void excludeClipRectangle (const Rectangle<int>& r) | |||
| { | |||
| android.activity.callVoidMethod (android.excludeClipRegion, getCanvas().get(), | |||
| android.activity.callVoidMethod (JuceAppActivity.excludeClipRegion, getCanvas().get(), | |||
| (float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom()); | |||
| } | |||
| void clipToPath (const Path& path, const AffineTransform& transform) | |||
| { | |||
| (void) getCanvas().callBooleanMethod (android.clipPath, createPath (getEnv(), path, transform).get()); | |||
| (void) getCanvas().callBooleanMethod (Canvas.clipPath, createPath (getEnv(), path, transform).get()); | |||
| } | |||
| void clipToImageAlpha (const Image& sourceImage, const AffineTransform& transform) | |||
| @@ -241,14 +343,14 @@ public: | |||
| Rectangle<int> bounds (getClipBounds()); | |||
| jobject temporaryLayerBitmap = AndroidImage::createBitmap (bounds.getWidth(), bounds.getHeight(), false); | |||
| jobject temporaryCanvas = env->NewObject (android.canvasClass, android.canvasBitmapConstructor, temporaryLayerBitmap); | |||
| jobject temporaryCanvas = env->NewObject (Canvas, Canvas.constructor, temporaryLayerBitmap); | |||
| setFill (Colours::red); | |||
| env->CallVoidMethod (temporaryCanvas, android.drawRect, | |||
| env->CallVoidMethod (temporaryCanvas, Canvas.drawRect, | |||
| (jfloat) 20, (jfloat) 20, (jfloat) 300, (jfloat) 200, | |||
| getCurrentPaint()); | |||
| env->CallVoidMethod (temporaryCanvas, android.translate, | |||
| env->CallVoidMethod (temporaryCanvas, Canvas.translate, | |||
| (jfloat) -bounds.getX(), (jfloat) -bounds.getY()); | |||
| Image maskImage (Image::SingleChannel, bounds.getWidth(), bounds.getHeight(), true); | |||
| @@ -273,12 +375,12 @@ public: | |||
| const Rectangle<int> getClipBounds() const | |||
| { | |||
| JNIEnv* env = getEnv(); | |||
| jobject rect = getCanvas().callObjectMethod (android.getClipBounds2); | |||
| jobject rect = getCanvas().callObjectMethod (Canvas.getClipBounds2); | |||
| const int left = env->GetIntField (rect, android.rectLeft); | |||
| const int top = env->GetIntField (rect, android.rectTop); | |||
| const int right = env->GetIntField (rect, android.rectRight); | |||
| const int bottom = env->GetIntField (rect, android.rectBottom); | |||
| const int left = env->GetIntField (rect, RectClass.left); | |||
| const int top = env->GetIntField (rect, RectClass.top); | |||
| const int right = env->GetIntField (rect, RectClass.right); | |||
| const int bottom = env->GetIntField (rect, RectClass.bottom); | |||
| env->DeleteLocalRef (rect); | |||
| return Rectangle<int> (left, top, right - left, bottom - top); | |||
| @@ -286,8 +388,8 @@ public: | |||
| bool isClipEmpty() const | |||
| { | |||
| LocalRef<jobject> tempRect (getEnv()->NewObject (android.rectClass, android.rectConstructor, 0, 0, 0, 0)); | |||
| return ! getCanvas().callBooleanMethod (android.getClipBounds, tempRect.get()); | |||
| LocalRef<jobject> tempRect (getEnv()->NewObject (RectClass, RectClass.constructor, 0, 0, 0, 0)); | |||
| return ! getCanvas().callBooleanMethod (Canvas.getClipBounds, tempRect.get()); | |||
| } | |||
| //============================================================================== | |||
| @@ -309,14 +411,14 @@ public: | |||
| //============================================================================== | |||
| void fillRect (const Rectangle<int>& r, bool replaceExistingContents) | |||
| { | |||
| getCanvas().callVoidMethod (android.drawRect, | |||
| getCanvas().callVoidMethod (Canvas.drawRect, | |||
| (float) r.getX(), (float) r.getY(), (float) r.getRight(), (float) r.getBottom(), | |||
| getCurrentPaint()); | |||
| } | |||
| void fillPath (const Path& path, const AffineTransform& transform) | |||
| { | |||
| getCanvas().callVoidMethod (android.drawPath, createPath (getEnv(), path, transform).get(), | |||
| getCanvas().callVoidMethod (Canvas.drawPath, createPath (getEnv(), path, transform).get(), | |||
| getCurrentPaint()); | |||
| } | |||
| @@ -327,7 +429,7 @@ public: | |||
| if (androidImage != 0) | |||
| { | |||
| JNIEnv* env = getEnv(); | |||
| getCanvas().callVoidMethod (android.drawBitmap, androidImage->bitmap.get(), | |||
| getCanvas().callVoidMethod (Canvas.drawBitmap, androidImage->bitmap.get(), | |||
| createMatrixRef (env, transform).get(), getImagePaint()); | |||
| } | |||
| else | |||
| @@ -362,7 +464,7 @@ public: | |||
| env->ReleaseIntArrayElements (imageData, dest, 0); | |||
| getCanvas().callVoidMethod (android.drawMemoryBitmap, imageData, 0, bm.width, | |||
| getCanvas().callVoidMethod (Canvas.drawMemoryBitmap, imageData, 0, bm.width, | |||
| transform.getTranslationX(), transform.getTranslationY(), | |||
| bm.width, bm.height, true, getImagePaint()); | |||
| env->DeleteLocalRef (imageData); | |||
| @@ -380,18 +482,18 @@ public: | |||
| void drawLine (const Line <float>& line) | |||
| { | |||
| getCanvas().callVoidMethod (android.drawLine, line.getStartX(), line.getStartY(), | |||
| getCanvas().callVoidMethod (Canvas.drawLine, line.getStartX(), line.getStartY(), | |||
| line.getEndX(), line.getEndY(), getCurrentPaint()); | |||
| } | |||
| void drawVerticalLine (int x, float top, float bottom) | |||
| { | |||
| getCanvas().callVoidMethod (android.drawRect, (float) x, top, x + 1.0f, bottom, getCurrentPaint()); | |||
| getCanvas().callVoidMethod (Canvas.drawRect, (float) x, top, x + 1.0f, bottom, getCurrentPaint()); | |||
| } | |||
| void drawHorizontalLine (int y, float left, float right) | |||
| { | |||
| getCanvas().callVoidMethod (android.drawRect, left, (float) y, right, y + 1.0f, getCurrentPaint()); | |||
| getCanvas().callVoidMethod (Canvas.drawRect, left, (float) y, right, y + 1.0f, getCurrentPaint()); | |||
| } | |||
| void setFont (const Font& newFont) | |||
| @@ -412,7 +514,7 @@ public: | |||
| { | |||
| if (transform.isOnlyTranslation()) | |||
| { | |||
| getCanvas().callVoidMethod (android.drawText, javaStringFromChar ((juce_wchar) glyphNumber).get(), | |||
| getCanvas().callVoidMethod (Canvas.drawText, javaStringFromChar ((juce_wchar) glyphNumber).get(), | |||
| transform.getTranslationX(), transform.getTranslationY(), | |||
| currentState->getPaintForTypeface()); | |||
| } | |||
| @@ -428,7 +530,7 @@ public: | |||
| //============================================================================== | |||
| void saveState() | |||
| { | |||
| (void) getCanvas().callIntMethod (android.save); | |||
| (void) getCanvas().callIntMethod (Canvas.save); | |||
| stateStack.add (new SavedState (*currentState)); | |||
| } | |||
| @@ -448,14 +550,14 @@ public: | |||
| jassertfalse; // trying to pop with an empty stack! | |||
| } | |||
| getCanvas().callVoidMethod (android.restore); | |||
| getCanvas().callVoidMethod (Canvas.restore); | |||
| } | |||
| void beginTransparencyLayer (float opacity) | |||
| { | |||
| Rectangle<int> clip (getClipBounds()); | |||
| (void) getCanvas().callIntMethod (android.saveLayerAlpha, | |||
| (void) getCanvas().callIntMethod (Canvas.saveLayerAlpha, | |||
| (float) clip.getX(), | |||
| (float) clip.getY(), | |||
| (float) clip.getRight(), | |||
| @@ -520,8 +622,8 @@ public: | |||
| if (fillType.isColour()) | |||
| { | |||
| env->DeleteLocalRef (paint.callObjectMethod (android.setShader, (jobject) 0)); | |||
| paint.callVoidMethod (android.setColor, colourToInt (fillType.colour)); | |||
| env->DeleteLocalRef (paint.callObjectMethod (Paint.setShader, (jobject) 0)); | |||
| paint.callVoidMethod (Paint.setColor, colourToInt (fillType.colour)); | |||
| } | |||
| else if (fillType.isGradient()) | |||
| { | |||
| @@ -547,13 +649,13 @@ public: | |||
| env->SetFloatArrayRegion (positionsArray, 0, numColours, positions.getData()); | |||
| } | |||
| jobject tileMode = env->GetStaticObjectField (android.shaderTileModeClass, android.clampMode); | |||
| jobject tileMode = env->GetStaticObjectField (ShaderTileMode, ShaderTileMode.CLAMP); | |||
| jobject shader; | |||
| if (fillType.gradient->isRadial) | |||
| { | |||
| shader = env->NewObject (android.radialGradientClass, | |||
| android.radialGradientConstructor, | |||
| shader = env->NewObject (RadialGradientClass, | |||
| RadialGradientClass.constructor, | |||
| p1.getX(), p1.getY(), | |||
| p1.getDistanceFrom (p2), | |||
| coloursArray, positionsArray, | |||
| @@ -561,8 +663,8 @@ public: | |||
| } | |||
| else | |||
| { | |||
| shader = env->NewObject (android.linearGradientClass, | |||
| android.linearGradientConstructor, | |||
| shader = env->NewObject (LinearGradientClass, | |||
| LinearGradientClass.constructor, | |||
| p1.getX(), p1.getY(), p2.getX(), p2.getY(), | |||
| coloursArray, positionsArray, | |||
| tileMode); | |||
| @@ -572,8 +674,8 @@ public: | |||
| env->DeleteLocalRef (coloursArray); | |||
| env->DeleteLocalRef (positionsArray); | |||
| env->CallVoidMethod (shader, android.setLocalMatrix, createMatrixRef (env, fillType.transform).get()); | |||
| env->DeleteLocalRef (paint.callObjectMethod (android.setShader, shader)); | |||
| env->CallVoidMethod (shader, ShaderClass.setLocalMatrix, createMatrixRef (env, fillType.transform).get()); | |||
| env->DeleteLocalRef (paint.callObjectMethod (Paint.setShader, shader)); | |||
| env->DeleteLocalRef (shader); | |||
| } | |||
| @@ -598,17 +700,17 @@ public: | |||
| if (atf != 0) | |||
| { | |||
| paint.callObjectMethod (android.setTypeface, atf->typeface.get()); | |||
| paint.callVoidMethod (android.setTextSize, font.getHeight()); | |||
| paint.callObjectMethod (Paint.setTypeface, atf->typeface.get()); | |||
| paint.callVoidMethod (Paint.setTextSize, font.getHeight()); | |||
| const float hScale = font.getHorizontalScale(); | |||
| if (hScale < 0.99f || hScale > 1.01f) | |||
| paint.callVoidMethod (android.setTextScaleX, hScale); | |||
| paint.callVoidMethod (Paint.setTextScaleX, hScale); | |||
| } | |||
| fillNeedsUpdate = true; | |||
| paint.callVoidMethod (android.setAlpha, (jint) fillType.colour.getAlpha()); | |||
| paint.callVoidMethod (Paint.setAlpha, (jint) fillType.colour.getAlpha()); | |||
| } | |||
| return p; | |||
| @@ -617,7 +719,7 @@ public: | |||
| jobject getImagePaint() | |||
| { | |||
| jobject p = getPaint(); | |||
| paint.callVoidMethod (android.setAlpha, (jint) fillType.colour.getAlpha()); | |||
| paint.callVoidMethod (Paint.setAlpha, (jint) fillType.colour.getAlpha()); | |||
| fillNeedsUpdate = true; | |||
| return p; | |||
| } | |||
| @@ -630,27 +732,27 @@ public: | |||
| { | |||
| JNIEnv* env = getEnv(); | |||
| jobject tileMode = env->GetStaticObjectField (android.shaderTileModeClass, android.clampMode); | |||
| jobject shader = env->NewObject (android.bitmapShaderClass, android.bitmapShaderConstructor, | |||
| jobject tileMode = env->GetStaticObjectField (ShaderTileMode, ShaderTileMode.CLAMP); | |||
| jobject shader = env->NewObject (BitmapShader, BitmapShader.constructor, | |||
| temporaryLayerBitmap.get(), tileMode, tileMode); | |||
| env->DeleteLocalRef (tileMode); | |||
| jobject compositingPaint = android.createPaint (quality); | |||
| env->CallObjectMethod (compositingPaint, android.setShader, shader); | |||
| env->CallObjectMethod (compositingPaint, Paint.setShader, shader); | |||
| env->DeleteLocalRef (shader); | |||
| LocalRef<jobject> maskBitmap (createAlphaBitmap (env, maskImage)); | |||
| maskImage = Image::null; | |||
| env->CallVoidMethod (previousCanvas, android.drawBitmapAt, | |||
| env->CallVoidMethod (previousCanvas, Canvas.drawBitmapAt, | |||
| maskBitmap.get(), (jfloat) maskLayerX, (jfloat) maskLayerY, compositingPaint); | |||
| env->DeleteLocalRef (compositingPaint); | |||
| canvas = GlobalRef (previousCanvas); | |||
| env->CallVoidMethod (temporaryLayerBitmap.get(), android.recycle); | |||
| env->CallVoidMethod (maskBitmap.get(), android.recycle); | |||
| env->CallVoidMethod (temporaryLayerBitmap.get(), BitmapClass.recycle); | |||
| env->CallVoidMethod (maskBitmap.get(), BitmapClass.recycle); | |||
| temporaryLayerBitmap.clear(); | |||
| } | |||
| @@ -693,7 +795,7 @@ public: | |||
| } | |||
| env->ReleaseIntArrayElements (intArray, (jint*) dest, 0); | |||
| env->CallVoidMethod (bitmap, android.setPixels, intArray, 0, bm.width, 0, 0, bm.width, bm.height); | |||
| env->CallVoidMethod (bitmap, BitmapClass.setPixels, intArray, 0, bm.width, 0, 0, bm.width, bm.height); | |||
| env->DeleteLocalRef (intArray); | |||
| return bitmap; | |||
| } | |||
| @@ -720,9 +822,9 @@ private: | |||
| jobject getCurrentPaint() const { return currentState->getPaint(); } | |||
| jobject getImagePaint() const { return currentState->getImagePaint(); } | |||
| static const LocalRef<jobject> createPath (JNIEnv* env, const Path& path) | |||
| static LocalRef<jobject> createPath (JNIEnv* env, const Path& path) | |||
| { | |||
| jobject p = env->NewObject (android.pathClass, android.pathClassConstructor); | |||
| jobject p = env->NewObject (PathClass, PathClass.constructor); | |||
| Path::Iterator i (path); | |||
| @@ -730,11 +832,11 @@ private: | |||
| { | |||
| switch (i.elementType) | |||
| { | |||
| case Path::Iterator::startNewSubPath: env->CallVoidMethod (p, android.moveTo, i.x1, i.y1); break; | |||
| case Path::Iterator::lineTo: env->CallVoidMethod (p, android.lineTo, i.x1, i.y1); break; | |||
| case Path::Iterator::quadraticTo: env->CallVoidMethod (p, android.quadTo, i.x1, i.y1, i.x2, i.y2); break; | |||
| case Path::Iterator::cubicTo: env->CallVoidMethod (p, android.cubicTo, i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); break; | |||
| case Path::Iterator::closePath: env->CallVoidMethod (p, android.closePath); break; | |||
| case Path::Iterator::startNewSubPath: env->CallVoidMethod (p, PathClass.moveTo, i.x1, i.y1); break; | |||
| case Path::Iterator::lineTo: env->CallVoidMethod (p, PathClass.lineTo, i.x1, i.y1); break; | |||
| case Path::Iterator::quadraticTo: env->CallVoidMethod (p, PathClass.quadTo, i.x1, i.y1, i.x2, i.y2); break; | |||
| case Path::Iterator::cubicTo: env->CallVoidMethod (p, PathClass.cubicTo, i.x1, i.y1, i.x2, i.y2, i.x3, i.y3); break; | |||
| case Path::Iterator::closePath: env->CallVoidMethod (p, PathClass.closePath); break; | |||
| default: jassertfalse; break; | |||
| } | |||
| } | |||
| @@ -742,7 +844,7 @@ private: | |||
| return LocalRef<jobject> (p); | |||
| } | |||
| static const LocalRef<jobject> createPath (JNIEnv* env, const Path& path, const AffineTransform& transform) | |||
| static LocalRef<jobject> createPath (JNIEnv* env, const Path& path, const AffineTransform& transform) | |||
| { | |||
| if (transform.isIdentity()) | |||
| return createPath (env, path); | |||
| @@ -752,25 +854,25 @@ private: | |||
| return createPath (env, tempPath); | |||
| } | |||
| static const LocalRef<jobject> createMatrixRef (JNIEnv* env, const AffineTransform& t) | |||
| static LocalRef<jobject> createMatrixRef (JNIEnv* env, const AffineTransform& t) | |||
| { | |||
| return LocalRef<jobject> (android.createMatrix (*env, t)); | |||
| return LocalRef<jobject> (android.createMatrix (env, t)); | |||
| } | |||
| static const LocalRef<jobject> createRect (JNIEnv* env, const Rectangle<int>& r) | |||
| static LocalRef<jobject> createRect (JNIEnv* env, const Rectangle<int>& r) | |||
| { | |||
| return LocalRef<jobject> (env->NewObject (android.rectClass, android.rectConstructor, | |||
| return LocalRef<jobject> (env->NewObject (RectClass, RectClass.constructor, | |||
| r.getX(), r.getY(), r.getRight(), r.getBottom())); | |||
| } | |||
| static const LocalRef<jobject> createRegion (JNIEnv* env, const RectangleList& list) | |||
| static LocalRef<jobject> createRegion (JNIEnv* env, const RectangleList& list) | |||
| { | |||
| jobject region = env->NewObject (android.regionClass, android.regionConstructor); | |||
| jobject region = env->NewObject (RegionClass, RegionClass.constructor); | |||
| const int numRects = list.getNumRectangles(); | |||
| for (int i = 0; i < numRects; ++i) | |||
| env->CallBooleanMethod (region, android.regionUnion, createRect (env, list.getRectangle(i)).get()); | |||
| env->CallBooleanMethod (region, RegionClass.regionUnion, createRect (env, list.getRectangle(i)).get()); | |||
| return LocalRef<jobject> (region); | |||
| } | |||
| @@ -795,7 +897,7 @@ private: | |||
| LowLevelGraphicsContext* AndroidImage::createLowLevelContext() | |||
| { | |||
| jobject canvas = getEnv()->NewObject (android.canvasClass, android.canvasBitmapConstructor, bitmap.get()); | |||
| jobject canvas = getEnv()->NewObject (Canvas, Canvas.constructor, bitmap.get()); | |||
| return new AndroidLowLevelGraphicsContext (canvas); | |||
| } | |||
| #endif | |||
| @@ -45,7 +45,7 @@ bool MessageManager::dispatchNextMessageOnSystemQueue (const bool returnIfNoPend | |||
| bool MessageManager::postMessageToSystemQueue (Message* message) | |||
| { | |||
| message->incReferenceCount(); | |||
| getEnv()->CallVoidMethod (android.activity, android.postMessage, (jlong) (pointer_sized_uint) message); | |||
| getEnv()->CallVoidMethod (android.activity, JuceAppActivity.postMessage, (jlong) (pointer_sized_uint) message); | |||
| return true; | |||
| } | |||
| @@ -111,7 +111,7 @@ public: | |||
| void messageCallback() | |||
| { | |||
| android.activity.callVoidMethod (android.finish); | |||
| android.activity.callVoidMethod (JuceAppActivity.finish); | |||
| } | |||
| }; | |||
| @@ -51,7 +51,7 @@ JUCE_JNI_CALLBACK (JuceAppActivity, quitApp, void, (JNIEnv* env, jobject activit | |||
| { | |||
| JUCEApplication::appWillTerminateByForce(); | |||
| android.shutdown(); | |||
| android.shutdown (env); | |||
| } | |||
| //============================================================================== | |||
| @@ -65,7 +65,7 @@ void Logger::outputDebugString (const String& text) | |||
| JNIEnv* const env = getEnv(); | |||
| if (env != nullptr) | |||
| env->CallStaticVoidMethod (android.activityClass, android.printToConsole, | |||
| env->CallStaticVoidMethod (JuceAppActivity, JuceAppActivity.printToConsole, | |||
| javaString (text).get()); | |||
| } | |||
| @@ -73,14 +73,13 @@ void Logger::outputDebugString (const String& text) | |||
| void SystemClipboard::copyTextToClipboard (const String& text) | |||
| { | |||
| const LocalRef<jstring> t (javaString (text)); | |||
| android.activity.callVoidMethod (android.setClipboardContent, t.get()); | |||
| android.activity.callVoidMethod (JuceAppActivity.setClipboardContent, t.get()); | |||
| } | |||
| String SystemClipboard::getTextFromClipboard() | |||
| { | |||
| const LocalRef<jstring> text ((jstring) android.activity.callObjectMethod (android.getClipboardContent)); | |||
| const LocalRef<jstring> text ((jstring) android.activity.callObjectMethod (JuceAppActivity.getClipboardContent)); | |||
| return juceString (text); | |||
| } | |||
| #endif | |||
| @@ -90,554 +90,14 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "../../audio/midi/juce_MidiInput.h" | |||
| #include "../../containers/juce_ScopedValueSetter.h" | |||
| #define USE_ANDROID_CANVAS 0 | |||
| //============================================================================== | |||
| #define JUCE_JNI_CALLBACK(className, methodName, returnType, params) \ | |||
| extern "C" __attribute__ ((visibility("default"))) returnType Java_com_juce_ ## className ## _ ## methodName params | |||
| //============================================================================== | |||
| // List of basic required classes | |||
| #define JUCE_JNI_CLASSES_ESSENTIAL(JAVACLASS) \ | |||
| JAVACLASS (activityClass, "com/juce/JuceAppActivity") \ | |||
| JAVACLASS (httpStreamClass, "com/juce/JuceAppActivity$HTTPStream") \ | |||
| JAVACLASS (componentPeerViewClass, "com/juce/ComponentPeerView") \ | |||
| JAVACLASS (fileClass, "java/io/File") \ | |||
| JAVACLASS (systemClass, "java/lang/System") \ | |||
| JAVACLASS (stringBufferClass, "java/lang/StringBuffer") \ | |||
| JAVACLASS (contextClass, "android/content/Context") \ | |||
| JAVACLASS (canvasClass, "android/graphics/Canvas") \ | |||
| JAVACLASS (paintClass, "android/graphics/Paint") \ | |||
| JAVACLASS (matrixClass, "android/graphics/Matrix") \ | |||
| JAVACLASS (rectClass, "android/graphics/Rect") \ | |||
| JAVACLASS (typefaceClass, "android/graphics/Typeface") \ | |||
| JAVACLASS (audioTrackClass, "android/media/AudioTrack") \ | |||
| JAVACLASS (audioRecordClass, "android/media/AudioRecord") \ | |||
| //============================================================================== | |||
| // List of extra classes needed when USE_ANDROID_CANVAS is enabled | |||
| #if ! USE_ANDROID_CANVAS | |||
| #define JUCE_JNI_CLASSES(JAVACLASS) JUCE_JNI_CLASSES_ESSENTIAL(JAVACLASS); | |||
| #else | |||
| #define JUCE_JNI_CLASSES(JAVACLASS) JUCE_JNI_CLASSES_ESSENTIAL(JAVACLASS); \ | |||
| JAVACLASS (pathClass, "android/graphics/Path") \ | |||
| JAVACLASS (regionClass, "android/graphics/Region") \ | |||
| JAVACLASS (bitmapClass, "android/graphics/Bitmap") \ | |||
| JAVACLASS (bitmapConfigClass, "android/graphics/Bitmap$Config") \ | |||
| JAVACLASS (bitmapShaderClass, "android/graphics/BitmapShader") \ | |||
| JAVACLASS (shaderClass, "android/graphics/Shader") \ | |||
| JAVACLASS (shaderTileModeClass, "android/graphics/Shader$TileMode") \ | |||
| JAVACLASS (linearGradientClass, "android/graphics/LinearGradient") \ | |||
| JAVACLASS (radialGradientClass, "android/graphics/RadialGradient") \ | |||
| #endif | |||
| //============================================================================== | |||
| // List of required methods | |||
| #define JUCE_JNI_METHODS_ESSENTIAL(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| \ | |||
| STATICMETHOD (activityClass, printToConsole, "printToConsole", "(Ljava/lang/String;)V") \ | |||
| METHOD (activityClass, createNewView, "createNewView", "(Z)Lcom/juce/ComponentPeerView;") \ | |||
| METHOD (activityClass, deleteView, "deleteView", "(Lcom/juce/ComponentPeerView;)V") \ | |||
| METHOD (activityClass, postMessage, "postMessage", "(J)V") \ | |||
| METHOD (activityClass, finish, "finish", "()V") \ | |||
| METHOD (activityClass, getClipboardContent, "getClipboardContent", "()Ljava/lang/String;") \ | |||
| METHOD (activityClass, setClipboardContent, "setClipboardContent", "(Ljava/lang/String;)V") \ | |||
| METHOD (activityClass, excludeClipRegion, "excludeClipRegion", "(Landroid/graphics/Canvas;FFFF)V") \ | |||
| METHOD (activityClass, renderGlyph, "renderGlyph", "(CLandroid/graphics/Paint;Landroid/graphics/Matrix;Landroid/graphics/Rect;)[I") \ | |||
| STATICMETHOD (activityClass, createHTTPStream, "createHTTPStream", "(Ljava/lang/String;Z[BLjava/lang/String;ILjava/lang/StringBuffer;)Lcom/juce/JuceAppActivity$HTTPStream;") \ | |||
| METHOD (activityClass, showMessageBox, "showMessageBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \ | |||
| METHOD (activityClass, showOkCancelBox, "showOkCancelBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \ | |||
| METHOD (activityClass, showYesNoCancelBox, "showYesNoCancelBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \ | |||
| \ | |||
| METHOD (stringBufferClass, stringBufferConstructor, "<init>", "()V") \ | |||
| METHOD (stringBufferClass, stringBufferToString, "toString", "()Ljava/lang/String;") \ | |||
| \ | |||
| METHOD (httpStreamClass, httpStreamRelease, "release", "()V") \ | |||
| METHOD (httpStreamClass, httpStreamRead, "read", "([BI)I") \ | |||
| METHOD (httpStreamClass, getPosition, "getPosition", "()J") \ | |||
| METHOD (httpStreamClass, getTotalLength, "getTotalLength", "()J") \ | |||
| METHOD (httpStreamClass, isExhausted, "isExhausted", "()Z") \ | |||
| METHOD (httpStreamClass, setPosition, "setPosition", "(J)Z") \ | |||
| \ | |||
| METHOD (fileClass, fileExists, "exists", "()Z") \ | |||
| STATICMETHOD (systemClass, getProperty, "getProperty", "(Ljava/lang/String;)Ljava/lang/String;") \ | |||
| \ | |||
| METHOD (componentPeerViewClass, setViewName, "setViewName", "(Ljava/lang/String;)V") \ | |||
| METHOD (componentPeerViewClass, layout, "layout", "(IIII)V") \ | |||
| METHOD (componentPeerViewClass, getLeft, "getLeft", "()I") \ | |||
| METHOD (componentPeerViewClass, getTop, "getTop", "()I") \ | |||
| METHOD (componentPeerViewClass, getWidth, "getWidth", "()I") \ | |||
| METHOD (componentPeerViewClass, getHeight, "getHeight", "()I") \ | |||
| METHOD (componentPeerViewClass, getLocationOnScreen, "getLocationOnScreen", "([I)V") \ | |||
| METHOD (componentPeerViewClass, bringToFront, "bringToFront", "()V") \ | |||
| METHOD (componentPeerViewClass, requestFocus, "requestFocus", "()Z") \ | |||
| METHOD (componentPeerViewClass, setVisible, "setVisible", "(Z)V") \ | |||
| METHOD (componentPeerViewClass, isVisible, "isVisible", "()Z") \ | |||
| METHOD (componentPeerViewClass, hasFocus, "hasFocus", "()Z") \ | |||
| METHOD (componentPeerViewClass, invalidate, "invalidate", "(IIII)V") \ | |||
| METHOD (componentPeerViewClass, containsPoint, "containsPoint", "(II)Z") \ | |||
| \ | |||
| METHOD (canvasClass, drawMemoryBitmap, "drawBitmap", "([IIIFFIIZLandroid/graphics/Paint;)V") \ | |||
| METHOD (canvasClass, getClipBounds2, "getClipBounds", "()Landroid/graphics/Rect;") \ | |||
| \ | |||
| METHOD (paintClass, paintClassConstructor, "<init>", "(I)V") \ | |||
| METHOD (paintClass, setColor, "setColor", "(I)V") \ | |||
| METHOD (paintClass, setAlpha, "setAlpha", "(I)V") \ | |||
| METHOD (paintClass, setTypeface, "setTypeface", "(Landroid/graphics/Typeface;)Landroid/graphics/Typeface;") \ | |||
| METHOD (paintClass, ascent, "ascent", "()F") \ | |||
| METHOD (paintClass, descent, "descent", "()F") \ | |||
| METHOD (paintClass, setTextSize, "setTextSize", "(F)V") \ | |||
| METHOD (paintClass, getTextWidths, "getTextWidths", "(Ljava/lang/String;[F)I") \ | |||
| METHOD (paintClass, setTextScaleX, "setTextScaleX", "(F)V") \ | |||
| METHOD (paintClass, getTextPath, "getTextPath", "(Ljava/lang/String;IIFFLandroid/graphics/Path;)V") \ | |||
| \ | |||
| METHOD (matrixClass, matrixClassConstructor, "<init>", "()V") \ | |||
| METHOD (matrixClass, setValues, "setValues", "([F)V") \ | |||
| \ | |||
| STATICMETHOD (typefaceClass, create, "create", "(Ljava/lang/String;I)Landroid/graphics/Typeface;") \ | |||
| STATICMETHOD (typefaceClass, createFromFile, "createFromFile", "(Ljava/lang/String;)Landroid/graphics/Typeface;") \ | |||
| \ | |||
| METHOD (rectClass, rectConstructor, "<init>", "(IIII)V") \ | |||
| FIELD (rectClass, rectLeft, "left", "I") \ | |||
| FIELD (rectClass, rectRight, "right", "I") \ | |||
| FIELD (rectClass, rectTop, "top", "I") \ | |||
| FIELD (rectClass, rectBottom, "bottom", "I") \ | |||
| \ | |||
| METHOD (audioTrackClass, audioTrackConstructor, "<init>", "(IIIIII)V") \ | |||
| STATICMETHOD (audioTrackClass, getMinBufferSize, "getMinBufferSize", "(III)I") \ | |||
| STATICMETHOD (audioTrackClass, getNativeOutputSampleRate, "getNativeOutputSampleRate", "(I)I") \ | |||
| METHOD (audioTrackClass, audioTrackPlay, "play", "()V") \ | |||
| METHOD (audioTrackClass, audioTrackStop, "stop", "()V") \ | |||
| METHOD (audioTrackClass, audioTrackRelease, "release", "()V") \ | |||
| METHOD (audioTrackClass, audioTrackFlush, "flush", "()V") \ | |||
| METHOD (audioTrackClass, audioTrackWrite, "write", "([SII)I") \ | |||
| \ | |||
| METHOD (audioRecordClass, audioRecordConstructor, "<init>", "(IIIII)V"); \ | |||
| STATICMETHOD (audioRecordClass, getMinRecordBufferSize, "getMinBufferSize", "(III)I") \ | |||
| METHOD (audioRecordClass, startRecording, "startRecording", "()V"); \ | |||
| METHOD (audioRecordClass, stopRecording, "stop", "()V"); \ | |||
| METHOD (audioRecordClass, audioRecordRead, "read", "([SII)I"); \ | |||
| METHOD (audioRecordClass, audioRecordRelease, "release", "()V"); \ | |||
| //============================================================================== | |||
| // List of extra methods needed when USE_ANDROID_CANVAS is enabled | |||
| #if ! USE_ANDROID_CANVAS | |||
| #define JUCE_JNI_METHODS(METHOD, STATICMETHOD, FIELD, STATICFIELD) JUCE_JNI_METHODS_ESSENTIAL(METHOD, STATICMETHOD, FIELD, STATICFIELD) | |||
| #else | |||
| #define JUCE_JNI_METHODS(METHOD, STATICMETHOD, FIELD, STATICFIELD) JUCE_JNI_METHODS_ESSENTIAL(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| METHOD (pathClass, pathClassConstructor, "<init>", "()V") \ | |||
| METHOD (pathClass, moveTo, "moveTo", "(FF)V") \ | |||
| METHOD (pathClass, lineTo, "lineTo", "(FF)V") \ | |||
| METHOD (pathClass, quadTo, "quadTo", "(FFFF)V") \ | |||
| METHOD (pathClass, cubicTo, "cubicTo", "(FFFFFF)V") \ | |||
| METHOD (pathClass, closePath, "close", "()V") \ | |||
| METHOD (pathClass, computeBounds, "computeBounds", "(Landroid/graphics/RectF;Z)V") \ | |||
| \ | |||
| STATICMETHOD (bitmapClass, createBitmap, "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;") \ | |||
| STATICFIELD (bitmapConfigClass, ARGB_8888, "ARGB_8888", "Landroid/graphics/Bitmap$Config;") \ | |||
| STATICFIELD (bitmapConfigClass, ALPHA_8, "ALPHA_8", "Landroid/graphics/Bitmap$Config;") \ | |||
| METHOD (bitmapClass, bitmapCopy, "copy", "(Landroid/graphics/Bitmap$Config;Z)Landroid/graphics/Bitmap;") \ | |||
| METHOD (bitmapClass, getPixels, "getPixels", "([IIIIIII)V") \ | |||
| METHOD (bitmapClass, setPixels, "setPixels", "([IIIIIII)V") \ | |||
| METHOD (bitmapClass, recycle, "recycle", "()V") \ | |||
| \ | |||
| METHOD (shaderClass, setLocalMatrix, "setLocalMatrix", "(Landroid/graphics/Matrix;)V") \ | |||
| STATICFIELD (shaderTileModeClass, clampMode, "CLAMP", "Landroid/graphics/Shader$TileMode;") \ | |||
| \ | |||
| METHOD (bitmapShaderClass, bitmapShaderConstructor, "<init>", "(Landroid/graphics/Bitmap;Landroid/graphics/Shader$TileMode;Landroid/graphics/Shader$TileMode;)V") \ | |||
| \ | |||
| METHOD (paintClass, setShader, "setShader", "(Landroid/graphics/Shader;)Landroid/graphics/Shader;") \ | |||
| \ | |||
| METHOD (canvasClass, canvasBitmapConstructor, "<init>", "(Landroid/graphics/Bitmap;)V") \ | |||
| METHOD (canvasClass, drawRect, "drawRect", "(FFFFLandroid/graphics/Paint;)V") \ | |||
| METHOD (canvasClass, translate, "translate", "(FF)V") \ | |||
| METHOD (canvasClass, clipPath, "clipPath", "(Landroid/graphics/Path;)Z") \ | |||
| METHOD (canvasClass, clipRect, "clipRect", "(FFFF)Z") \ | |||
| METHOD (canvasClass, clipRegion, "clipRegion", "(Landroid/graphics/Region;)Z") \ | |||
| METHOD (canvasClass, concat, "concat", "(Landroid/graphics/Matrix;)V") \ | |||
| METHOD (canvasClass, drawBitmap, "drawBitmap", "(Landroid/graphics/Bitmap;Landroid/graphics/Matrix;Landroid/graphics/Paint;)V") \ | |||
| METHOD (canvasClass, drawBitmapAt, "drawBitmap", "(Landroid/graphics/Bitmap;FFLandroid/graphics/Paint;)V") \ | |||
| METHOD (canvasClass, drawLine, "drawLine", "(FFFFLandroid/graphics/Paint;)V") \ | |||
| METHOD (canvasClass, drawPath, "drawPath", "(Landroid/graphics/Path;Landroid/graphics/Paint;)V") \ | |||
| METHOD (canvasClass, drawText, "drawText", "(Ljava/lang/String;FFLandroid/graphics/Paint;)V") \ | |||
| METHOD (canvasClass, getClipBounds, "getClipBounds", "(Landroid/graphics/Rect;)Z") \ | |||
| METHOD (canvasClass, getMatrix, "getMatrix", "()Landroid/graphics/Matrix;") \ | |||
| METHOD (canvasClass, save, "save", "()I") \ | |||
| METHOD (canvasClass, restore, "restore", "()V") \ | |||
| METHOD (canvasClass, saveLayerAlpha, "saveLayerAlpha", "(FFFFII)I") \ | |||
| \ | |||
| METHOD (linearGradientClass, linearGradientConstructor, "<init>", "(FFFF[I[FLandroid/graphics/Shader$TileMode;)V") \ | |||
| \ | |||
| METHOD (radialGradientClass, radialGradientConstructor, "<init>", "(FFF[I[FLandroid/graphics/Shader$TileMode;)V") \ | |||
| \ | |||
| METHOD (regionClass, regionConstructor, "<init>", "()V"); \ | |||
| METHOD (regionClass, regionUnion, "union", "(Landroid/graphics/Rect;)Z"); \ | |||
| #endif | |||
| //============================================================================== | |||
| class ThreadLocalJNIEnvHolder | |||
| { | |||
| public: | |||
| ThreadLocalJNIEnvHolder() | |||
| : jvm (0) | |||
| { | |||
| zeromem (threads, sizeof (threads)); | |||
| zeromem (envs, sizeof (envs)); | |||
| } | |||
| void initialise (JNIEnv* env) | |||
| { | |||
| env->GetJavaVM (&jvm); | |||
| addEnv (env); | |||
| } | |||
| void attach() | |||
| { | |||
| JNIEnv* env = nullptr; | |||
| jvm->AttachCurrentThread (&env, 0); | |||
| if (env != 0) | |||
| addEnv (env); | |||
| } | |||
| void detach() | |||
| { | |||
| jvm->DetachCurrentThread(); | |||
| const pthread_t thisThread = pthread_self(); | |||
| SpinLock::ScopedLockType sl (addRemoveLock); | |||
| for (int i = 0; i < maxThreads; ++i) | |||
| if (threads[i] == thisThread) | |||
| threads[i] = 0; | |||
| } | |||
| JNIEnv* get() const noexcept | |||
| { | |||
| const pthread_t thisThread = pthread_self(); | |||
| for (int i = 0; i < maxThreads; ++i) | |||
| if (threads[i] == thisThread) | |||
| return envs[i]; | |||
| return nullptr; | |||
| } | |||
| enum { maxThreads = 16 }; | |||
| private: | |||
| JavaVM* jvm; | |||
| pthread_t threads [maxThreads]; | |||
| JNIEnv* envs [maxThreads]; | |||
| SpinLock addRemoveLock; | |||
| void addEnv (JNIEnv* env) | |||
| { | |||
| SpinLock::ScopedLockType sl (addRemoveLock); | |||
| if (get() == 0) | |||
| { | |||
| const pthread_t thisThread = pthread_self(); | |||
| for (int i = 0; i < maxThreads; ++i) | |||
| { | |||
| if (threads[i] == 0) | |||
| { | |||
| envs[i] = env; | |||
| threads[i] = thisThread; | |||
| return; | |||
| } | |||
| } | |||
| } | |||
| jassertfalse; // too many threads! | |||
| } | |||
| }; | |||
| static ThreadLocalJNIEnvHolder threadLocalJNIEnvHolder; | |||
| struct AndroidThreadScope | |||
| { | |||
| AndroidThreadScope() { threadLocalJNIEnvHolder.attach(); } | |||
| ~AndroidThreadScope() { threadLocalJNIEnvHolder.detach(); } | |||
| }; | |||
| static inline JNIEnv* getEnv() noexcept | |||
| { | |||
| return threadLocalJNIEnvHolder.get(); | |||
| } | |||
| //============================================================================== | |||
| class GlobalRef | |||
| { | |||
| public: | |||
| inline GlobalRef() noexcept | |||
| : obj (0) | |||
| { | |||
| } | |||
| inline explicit GlobalRef (jobject obj_) | |||
| : obj (retain (obj_)) | |||
| { | |||
| } | |||
| inline GlobalRef (const GlobalRef& other) | |||
| : obj (retain (other.obj)) | |||
| { | |||
| } | |||
| ~GlobalRef() | |||
| { | |||
| clear(); | |||
| } | |||
| inline void clear() | |||
| { | |||
| if (obj != 0) | |||
| { | |||
| getEnv()->DeleteGlobalRef (obj); | |||
| obj = 0; | |||
| } | |||
| } | |||
| inline GlobalRef& operator= (const GlobalRef& other) | |||
| { | |||
| clear(); | |||
| obj = retain (other.obj); | |||
| return *this; | |||
| } | |||
| //============================================================================== | |||
| inline operator jobject() const noexcept { return obj; } | |||
| inline jobject get() const noexcept { return obj; } | |||
| //============================================================================== | |||
| #define DECLARE_CALL_TYPE_METHOD(returnType, typeName) \ | |||
| returnType call##typeName##Method (jmethodID methodID, ... ) const \ | |||
| { \ | |||
| va_list args; \ | |||
| va_start (args, methodID); \ | |||
| returnType result = getEnv()->Call##typeName##MethodV (obj, methodID, args); \ | |||
| va_end (args); \ | |||
| return result; \ | |||
| } | |||
| DECLARE_CALL_TYPE_METHOD (jobject, Object) | |||
| DECLARE_CALL_TYPE_METHOD (jboolean, Boolean) | |||
| DECLARE_CALL_TYPE_METHOD (jbyte, Byte) | |||
| DECLARE_CALL_TYPE_METHOD (jchar, Char) | |||
| DECLARE_CALL_TYPE_METHOD (jshort, Short) | |||
| DECLARE_CALL_TYPE_METHOD (jint, Int) | |||
| DECLARE_CALL_TYPE_METHOD (jlong, Long) | |||
| DECLARE_CALL_TYPE_METHOD (jfloat, Float) | |||
| DECLARE_CALL_TYPE_METHOD (jdouble, Double) | |||
| #undef DECLARE_CALL_TYPE_METHOD | |||
| void callVoidMethod (jmethodID methodID, ... ) const | |||
| { | |||
| va_list args; | |||
| va_start (args, methodID); | |||
| getEnv()->CallVoidMethodV (obj, methodID, args); | |||
| va_end (args); | |||
| } | |||
| private: | |||
| //============================================================================== | |||
| jobject obj; | |||
| static inline jobject retain (jobject obj_) | |||
| { | |||
| return obj_ == 0 ? 0 : getEnv()->NewGlobalRef (obj_); | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| template <typename JavaType> | |||
| class LocalRef | |||
| { | |||
| public: | |||
| explicit inline LocalRef (JavaType obj_) noexcept | |||
| : obj (obj_) | |||
| { | |||
| } | |||
| inline LocalRef (const LocalRef& other) noexcept | |||
| : obj (retain (other.obj)) | |||
| { | |||
| } | |||
| ~LocalRef() | |||
| { | |||
| if (obj != 0) | |||
| getEnv()->DeleteLocalRef (obj); | |||
| } | |||
| LocalRef& operator= (const LocalRef& other) | |||
| { | |||
| if (obj != other.obj) | |||
| { | |||
| if (obj != 0) | |||
| getEnv()->DeleteLocalRef (obj); | |||
| obj = retain (other.obj); | |||
| } | |||
| return *this; | |||
| } | |||
| inline operator JavaType() const noexcept { return obj; } | |||
| inline JavaType get() const noexcept { return obj; } | |||
| private: | |||
| JavaType obj; | |||
| static JavaType retain (JavaType obj_) | |||
| { | |||
| return obj_ == 0 ? 0 : (JavaType) getEnv()->NewLocalRef (obj_); | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| static const String juceString (jstring s) | |||
| { | |||
| JNIEnv* env = getEnv(); | |||
| jboolean isCopy; | |||
| const char* const utf8 = env->GetStringUTFChars (s, &isCopy); | |||
| CharPointer_UTF8 utf8CP (utf8); | |||
| const String result (utf8CP); | |||
| env->ReleaseStringUTFChars (s, utf8); | |||
| return result; | |||
| } | |||
| static const LocalRef<jstring> javaString (const String& s) | |||
| { | |||
| return LocalRef<jstring> (getEnv()->NewStringUTF (s.toUTF8())); | |||
| } | |||
| static const LocalRef<jstring> javaStringFromChar (const juce_wchar c) | |||
| { | |||
| char utf8[5] = { 0 }; | |||
| CharPointer_UTF8 (utf8).write (c); | |||
| return LocalRef<jstring> (getEnv()->NewStringUTF (utf8)); | |||
| } | |||
| //============================================================================== | |||
| class AndroidJavaCallbacks | |||
| { | |||
| public: | |||
| AndroidJavaCallbacks() : screenWidth (0), screenHeight (0) | |||
| { | |||
| } | |||
| void initialise (JNIEnv* env, jobject activity_, | |||
| jstring appFile_, jstring appDataDir_) | |||
| { | |||
| threadLocalJNIEnvHolder.initialise (env); | |||
| activity = GlobalRef (activity_); | |||
| appFile = juceString (appFile_); | |||
| appDataDir = juceString (appDataDir_); | |||
| #define CREATE_JNI_CLASS(className, path) \ | |||
| className = (jclass) env->NewGlobalRef (env->FindClass (path)); \ | |||
| jassert (className != 0); | |||
| JUCE_JNI_CLASSES (CREATE_JNI_CLASS); | |||
| #undef CREATE_JNI_CLASS | |||
| #define CREATE_JNI_METHOD(ownerClass, methodID, stringName, params) \ | |||
| methodID = env->GetMethodID (ownerClass, stringName, params); \ | |||
| jassert (methodID != 0); | |||
| #define CREATE_JNI_STATICMETHOD(ownerClass, methodID, stringName, params) \ | |||
| methodID = env->GetStaticMethodID (ownerClass, stringName, params); \ | |||
| jassert (methodID != 0); | |||
| #define CREATE_JNI_FIELD(ownerClass, fieldID, stringName, signature) \ | |||
| fieldID = env->GetFieldID (ownerClass, stringName, signature); \ | |||
| jassert (fieldID != 0); | |||
| #define CREATE_JNI_STATICFIELD(ownerClass, fieldID, stringName, signature) \ | |||
| fieldID = env->GetStaticFieldID (ownerClass, stringName, signature); \ | |||
| jassert (fieldID != 0); | |||
| JUCE_JNI_METHODS (CREATE_JNI_METHOD, CREATE_JNI_STATICMETHOD, CREATE_JNI_FIELD, CREATE_JNI_STATICFIELD); | |||
| #undef CREATE_JNI_METHOD | |||
| } | |||
| void shutdown() | |||
| { | |||
| JNIEnv* env = getEnv(); | |||
| if (env != 0) | |||
| { | |||
| #define RELEASE_JNI_CLASS(className, path) env->DeleteGlobalRef (className); | |||
| JUCE_JNI_CLASSES (RELEASE_JNI_CLASS); | |||
| #undef RELEASE_JNI_CLASS | |||
| activity.clear(); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| GlobalRef activity; | |||
| String appFile, appDataDir; | |||
| int screenWidth, screenHeight; | |||
| jobject createPaint (Graphics::ResamplingQuality quality) | |||
| { | |||
| jint constructorFlags = 1 /*ANTI_ALIAS_FLAG*/ | |||
| | 4 /*DITHER_FLAG*/ | |||
| | 128 /*SUBPIXEL_TEXT_FLAG*/; | |||
| if (quality > Graphics::lowResamplingQuality) | |||
| constructorFlags |= 2; /*FILTER_BITMAP_FLAG*/ | |||
| return getEnv()->NewObject (paintClass, paintClassConstructor, constructorFlags); | |||
| } | |||
| const jobject createMatrix (JNIEnv* env, const AffineTransform& t) | |||
| { | |||
| jobject m = env->NewObject (matrixClass, matrixClassConstructor); | |||
| jfloat values[9] = { t.mat00, t.mat01, t.mat02, | |||
| t.mat10, t.mat11, t.mat12, | |||
| 0.0f, 0.0f, 1.0f }; | |||
| jfloatArray javaArray = env->NewFloatArray (9); | |||
| env->SetFloatArrayRegion (javaArray, 0, 9, values); | |||
| env->CallVoidMethod (m, setValues, javaArray); | |||
| env->DeleteLocalRef (javaArray); | |||
| return m; | |||
| } | |||
| //============================================================================== | |||
| #define DECLARE_JNI_CLASS(className, path) jclass className; | |||
| JUCE_JNI_CLASSES (DECLARE_JNI_CLASS); | |||
| #undef DECLARE_JNI_CLASS | |||
| #define DECLARE_JNI_METHOD(ownerClass, methodID, stringName, params) jmethodID methodID; | |||
| #define DECLARE_JNI_FIELD(ownerClass, fieldID, stringName, signature) jfieldID fieldID; | |||
| JUCE_JNI_METHODS (DECLARE_JNI_METHOD, DECLARE_JNI_METHOD, DECLARE_JNI_FIELD, DECLARE_JNI_FIELD); | |||
| #undef DECLARE_JNI_METHOD | |||
| }; | |||
| static AndroidJavaCallbacks android; | |||
| // This is an unsatisfactory workaround for a linker warning that appeared in NDK5c. | |||
| // If anyone actually understands what this symbol is for and why the linker gets confused by it, | |||
| // please let me know! | |||
| extern "C" { void* __dso_handle = 0; } | |||
| #include "juce_android_JNIHelpers.h" | |||
| //============================================================================== | |||
| #define JUCE_INCLUDED_FILE 1 | |||
| // Now include the actual code files.. | |||
| #include "juce_android_Misc.cpp" | |||
| #include "juce_android_SystemStats.cpp" | |||
| #include "juce_android_Misc.cpp" | |||
| #include "../common/juce_posix_SharedCode.h" | |||
| #include "juce_android_Files.cpp" | |||
| #include "../common/juce_posix_NamedPipe.cpp" | |||
| @@ -27,6 +27,26 @@ | |||
| // compiled on its own). | |||
| #if JUCE_INCLUDED_FILE | |||
| //============================================================================== | |||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| METHOD (constructor, "<init>", "()V") \ | |||
| METHOD (toString, "toString", "()Ljava/lang/String;") \ | |||
| DECLARE_JNI_CLASS (StringBuffer, "java/lang/StringBuffer"); | |||
| #undef JNI_CLASS_MEMBERS | |||
| //============================================================================== | |||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| METHOD (release, "release", "()V") \ | |||
| METHOD (read, "read", "([BI)I") \ | |||
| METHOD (getPosition, "getPosition", "()J") \ | |||
| METHOD (getTotalLength, "getTotalLength", "()J") \ | |||
| METHOD (isExhausted, "isExhausted", "()Z") \ | |||
| METHOD (setPosition, "setPosition", "(J)Z") \ | |||
| DECLARE_JNI_CLASS (HTTPStream, "com/juce/JuceAppActivity$HTTPStream"); | |||
| #undef JNI_CLASS_MEMBERS | |||
| //============================================================================== | |||
| void MACAddress::findAllAddresses (Array<MACAddress>& result) | |||
| @@ -67,10 +87,10 @@ public: | |||
| env->SetByteArrayRegion (postDataArray, 0, postData.getSize(), (const jbyte*) postData.getData()); | |||
| } | |||
| LocalRef<jobject> responseHeaderBuffer (env->NewObject (android.stringBufferClass, android.stringBufferConstructor)); | |||
| LocalRef<jobject> responseHeaderBuffer (env->NewObject (StringBuffer, StringBuffer.constructor)); | |||
| stream = GlobalRef (env->CallStaticObjectMethod (android.activityClass, | |||
| android.createHTTPStream, | |||
| stream = GlobalRef (env->CallStaticObjectMethod (JuceAppActivity, | |||
| JuceAppActivity.createHTTPStream, | |||
| javaString (address).get(), | |||
| (jboolean) isPost, | |||
| postDataArray, | |||
| @@ -87,8 +107,8 @@ public: | |||
| { | |||
| LocalRef<jstring> headersString ((jstring) env->CallObjectMethod (responseHeaderBuffer.get(), | |||
| android.stringBufferToString)); | |||
| headerLines.addLines (juceString (headersString)); | |||
| StringBuffer.toString)); | |||
| headerLines.addLines (juceString (env, headersString)); | |||
| } | |||
| if (responseHeaders != 0) | |||
| @@ -109,14 +129,14 @@ public: | |||
| ~WebInputStream() | |||
| { | |||
| if (stream != 0) | |||
| stream.callVoidMethod (android.httpStreamRelease); | |||
| stream.callVoidMethod (HTTPStream.release); | |||
| } | |||
| //============================================================================== | |||
| bool isExhausted() { return stream != nullptr && stream.callBooleanMethod (android.isExhausted); } | |||
| int64 getTotalLength() { return stream != nullptr ? stream.callLongMethod (android.getTotalLength) : 0; } | |||
| int64 getPosition() { return stream != nullptr ? stream.callLongMethod (android.getPosition) : 0; } | |||
| bool setPosition (int64 wantedPos) { return stream != nullptr && stream.callBooleanMethod (android.setPosition, (jlong) wantedPos); } | |||
| bool isExhausted() { return stream != nullptr && stream.callBooleanMethod (HTTPStream.isExhausted); } | |||
| int64 getTotalLength() { return stream != nullptr ? stream.callLongMethod (HTTPStream.getTotalLength) : 0; } | |||
| int64 getPosition() { return stream != nullptr ? stream.callLongMethod (HTTPStream.getPosition) : 0; } | |||
| bool setPosition (int64 wantedPos) { return stream != nullptr && stream.callBooleanMethod (HTTPStream.setPosition, (jlong) wantedPos); } | |||
| int read (void* buffer, int bytesToRead) | |||
| { | |||
| @@ -127,7 +147,7 @@ public: | |||
| jbyteArray javaArray = env->NewByteArray (bytesToRead); | |||
| int numBytes = stream.callIntMethod (android.httpStreamRead, javaArray, (jint) bytesToRead); | |||
| int numBytes = stream.callIntMethod (HTTPStream.read, javaArray, (jint) bytesToRead); | |||
| if (numBytes > 0) | |||
| env->GetByteArrayRegion (javaArray, 0, numBytes, static_cast <jbyte*> (buffer)); | |||
| @@ -27,13 +27,234 @@ | |||
| // compiled on its own). | |||
| #if JUCE_INCLUDED_FILE | |||
| //============================================================================== | |||
| JNIClassBase::JNIClassBase (const char* classPath_) | |||
| : classPath (classPath_), classRef (0) | |||
| { | |||
| getClasses().add (this); | |||
| } | |||
| JNIClassBase::~JNIClassBase() | |||
| { | |||
| getClasses().removeValue (this); | |||
| } | |||
| Array<JNIClassBase*>& JNIClassBase::getClasses() | |||
| { | |||
| static Array<JNIClassBase*> classes; | |||
| return classes; | |||
| } | |||
| void JNIClassBase::initialise (JNIEnv* env) | |||
| { | |||
| classRef = (jclass) env->NewGlobalRef (env->FindClass (classPath)); | |||
| jassert (classRef != 0); | |||
| initialiseFields (env); | |||
| } | |||
| void JNIClassBase::release (JNIEnv* env) | |||
| { | |||
| env->DeleteGlobalRef (classRef); | |||
| } | |||
| void JNIClassBase::initialiseAllClasses (JNIEnv* env) | |||
| { | |||
| Array<JNIClassBase*>& classes = getClasses(); | |||
| for (int i = classes.size(); --i >= 0;) | |||
| classes.getUnchecked(i)->initialise (env); | |||
| } | |||
| void JNIClassBase::releaseAllClasses (JNIEnv* env) | |||
| { | |||
| Array<JNIClassBase*>& classes = getClasses(); | |||
| for (int i = classes.size(); --i >= 0;) | |||
| classes.getUnchecked(i)->release (env); | |||
| } | |||
| jmethodID JNIClassBase::resolveMethod (JNIEnv* env, const char* methodName, const char* params) | |||
| { | |||
| jmethodID m = env->GetMethodID (classRef, methodName, params); | |||
| jassert (m != 0); | |||
| return m; | |||
| } | |||
| jmethodID JNIClassBase::resolveStaticMethod (JNIEnv* env, const char* methodName, const char* params) | |||
| { | |||
| jmethodID m = env->GetStaticMethodID (classRef, methodName, params); | |||
| jassert (m != 0); | |||
| return m; | |||
| } | |||
| jfieldID JNIClassBase::resolveField (JNIEnv* env, const char* fieldName, const char* signature) | |||
| { | |||
| jfieldID f = env->GetFieldID (classRef, fieldName, signature); | |||
| jassert (f != 0); | |||
| return f; | |||
| } | |||
| jfieldID JNIClassBase::resolveStaticField (JNIEnv* env, const char* fieldName, const char* signature) | |||
| { | |||
| jfieldID f = env->GetStaticFieldID (classRef, fieldName, signature); | |||
| jassert (f != 0); | |||
| return f; | |||
| } | |||
| //============================================================================== | |||
| class ThreadLocalJNIEnvHolder | |||
| { | |||
| public: | |||
| ThreadLocalJNIEnvHolder() | |||
| : jvm (nullptr) | |||
| { | |||
| zeromem (threads, sizeof (threads)); | |||
| zeromem (envs, sizeof (envs)); | |||
| } | |||
| void initialise (JNIEnv* env) | |||
| { | |||
| env->GetJavaVM (&jvm); | |||
| addEnv (env); | |||
| } | |||
| void attach() | |||
| { | |||
| JNIEnv* env = nullptr; | |||
| jvm->AttachCurrentThread (&env, 0); | |||
| if (env != 0) | |||
| addEnv (env); | |||
| } | |||
| void detach() | |||
| { | |||
| jvm->DetachCurrentThread(); | |||
| const pthread_t thisThread = pthread_self(); | |||
| SpinLock::ScopedLockType sl (addRemoveLock); | |||
| for (int i = 0; i < maxThreads; ++i) | |||
| if (threads[i] == thisThread) | |||
| threads[i] = 0; | |||
| } | |||
| JNIEnv* get() const noexcept | |||
| { | |||
| const pthread_t thisThread = pthread_self(); | |||
| for (int i = 0; i < maxThreads; ++i) | |||
| if (threads[i] == thisThread) | |||
| return envs[i]; | |||
| return nullptr; | |||
| } | |||
| enum { maxThreads = 16 }; | |||
| private: | |||
| JavaVM* jvm; | |||
| pthread_t threads [maxThreads]; | |||
| JNIEnv* envs [maxThreads]; | |||
| SpinLock addRemoveLock; | |||
| void addEnv (JNIEnv* env) | |||
| { | |||
| SpinLock::ScopedLockType sl (addRemoveLock); | |||
| if (get() == nullptr) | |||
| { | |||
| const pthread_t thisThread = pthread_self(); | |||
| for (int i = 0; i < maxThreads; ++i) | |||
| { | |||
| if (threads[i] == 0) | |||
| { | |||
| envs[i] = env; | |||
| threads[i] = thisThread; | |||
| return; | |||
| } | |||
| } | |||
| } | |||
| jassertfalse; // too many threads! | |||
| } | |||
| }; | |||
| static ThreadLocalJNIEnvHolder threadLocalJNIEnvHolder; | |||
| JNIEnv* getEnv() noexcept | |||
| { | |||
| return threadLocalJNIEnvHolder.get(); | |||
| } | |||
| //============================================================================== | |||
| AndroidSystem::AndroidSystem() : screenWidth (0), screenHeight (0) | |||
| { | |||
| } | |||
| void AndroidSystem::initialise (JNIEnv* env, jobject activity_, | |||
| jstring appFile_, jstring appDataDir_) | |||
| { | |||
| JNIClassBase::initialiseAllClasses (env); | |||
| threadLocalJNIEnvHolder.initialise (env); | |||
| activity = GlobalRef (activity_); | |||
| appFile = juceString (env, appFile_); | |||
| appDataDir = juceString (env, appDataDir_); | |||
| } | |||
| void AndroidSystem::shutdown (JNIEnv* env) | |||
| { | |||
| activity.clear(); | |||
| JNIClassBase::releaseAllClasses (env); | |||
| } | |||
| jobject AndroidSystem::createPaint (Graphics::ResamplingQuality quality) | |||
| { | |||
| jint constructorFlags = 1 /*ANTI_ALIAS_FLAG*/ | |||
| | 4 /*DITHER_FLAG*/ | |||
| | 128 /*SUBPIXEL_TEXT_FLAG*/; | |||
| if (quality > Graphics::lowResamplingQuality) | |||
| constructorFlags |= 2; /*FILTER_BITMAP_FLAG*/ | |||
| return getEnv()->NewObject (Paint, Paint.constructor, constructorFlags); | |||
| } | |||
| const jobject AndroidSystem::createMatrix (JNIEnv* env, const AffineTransform& t) | |||
| { | |||
| jobject m = env->NewObject (Matrix, Matrix.constructor); | |||
| jfloat values[9] = { t.mat00, t.mat01, t.mat02, | |||
| t.mat10, t.mat11, t.mat12, | |||
| 0.0f, 0.0f, 1.0f }; | |||
| jfloatArray javaArray = env->NewFloatArray (9); | |||
| env->SetFloatArrayRegion (javaArray, 0, 9, values); | |||
| env->CallVoidMethod (m, Matrix.setValues, javaArray); | |||
| env->DeleteLocalRef (javaArray); | |||
| return m; | |||
| } | |||
| AndroidSystem android; | |||
| //============================================================================== | |||
| namespace AndroidStatsHelpers | |||
| { | |||
| //============================================================================== | |||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| STATICMETHOD (getProperty, "getProperty", "(Ljava/lang/String;)Ljava/lang/String;") | |||
| DECLARE_JNI_CLASS (SystemClass, "java/lang/System"); | |||
| #undef JNI_CLASS_MEMBERS | |||
| //============================================================================== | |||
| String getSystemProperty (const String& name) | |||
| { | |||
| return juceString (LocalRef<jstring> ((jstring) getEnv()->CallStaticObjectMethod (android.systemClass, | |||
| android.getProperty, | |||
| return juceString (LocalRef<jstring> ((jstring) getEnv()->CallStaticObjectMethod (SystemClass, | |||
| SystemClass.getProperty, | |||
| javaString (name).get()))); | |||
| } | |||
| } | |||
| @@ -51,11 +272,11 @@ String SystemStats::getOperatingSystemName() | |||
| bool SystemStats::isOperatingSystem64Bit() | |||
| { | |||
| #if JUCE_64BIT | |||
| #if JUCE_64BIT | |||
| return true; | |||
| #else | |||
| #else | |||
| return false; | |||
| #endif | |||
| #endif | |||
| } | |||
| String SystemStats::getCpuVendor() | |||
| @@ -70,13 +291,11 @@ int SystemStats::getCpuSpeedInMegaherz() | |||
| int SystemStats::getMemorySizeInMegabytes() | |||
| { | |||
| // xxx they forgot to implement sysinfo in the library, dammit! Should put this stuff back when they fix it. | |||
| /* struct sysinfo sysi; | |||
| struct sysinfo sysi; | |||
| if (sysinfo (&sysi) == 0) | |||
| return (sysi.totalram * sysi.mem_unit / (1024 * 1024)); | |||
| */ | |||
| DBG ("warning! memory size is unavailable due to an Android bug!"); | |||
| return 0; | |||
| } | |||
| @@ -159,5 +378,10 @@ bool Time::setSystemTimeToThisTime() const | |||
| return false; | |||
| } | |||
| //============================================================================== | |||
| // This is an unsatisfactory workaround for a linker warning that appeared in NDK5c. | |||
| // If anyone actually understands what this symbol is for and why the linker gets confused by it, | |||
| // please let me know! | |||
| extern "C" { void* __dso_handle = 0; } | |||
| #endif | |||
| @@ -27,6 +27,34 @@ | |||
| // compiled on its own). | |||
| #if JUCE_INCLUDED_FILE | |||
| //============================================================================== | |||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| METHOD (drawBitmap, "drawBitmap", "([IIIFFIIZLandroid/graphics/Paint;)V") \ | |||
| METHOD (getClipBounds, "getClipBounds", "()Landroid/graphics/Rect;") | |||
| DECLARE_JNI_CLASS (CanvasMinimal, "android/graphics/Canvas"); | |||
| #undef JNI_CLASS_MEMBERS | |||
| //============================================================================== | |||
| #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ | |||
| METHOD (setViewName, "setViewName", "(Ljava/lang/String;)V") \ | |||
| METHOD (layout, "layout", "(IIII)V") \ | |||
| METHOD (getLeft, "getLeft", "()I") \ | |||
| METHOD (getTop, "getTop", "()I") \ | |||
| METHOD (getWidth, "getWidth", "()I") \ | |||
| METHOD (getHeight, "getHeight", "()I") \ | |||
| METHOD (getLocationOnScreen, "getLocationOnScreen", "([I)V") \ | |||
| METHOD (bringToFront, "bringToFront", "()V") \ | |||
| METHOD (requestFocus, "requestFocus", "()Z") \ | |||
| METHOD (setVisible, "setVisible", "(Z)V") \ | |||
| METHOD (isVisible, "isVisible", "()Z") \ | |||
| METHOD (hasFocus, "hasFocus", "()Z") \ | |||
| METHOD (invalidate, "invalidate", "(IIII)V") \ | |||
| METHOD (containsPoint, "containsPoint", "(II)Z") \ | |||
| DECLARE_JNI_CLASS (ComponentPeerView, "com/juce/ComponentPeerView"); | |||
| #undef JNI_CLASS_MEMBERS | |||
| //============================================================================== | |||
| class AndroidComponentPeer : public ComponentPeer | |||
| @@ -35,7 +63,7 @@ public: | |||
| //============================================================================== | |||
| AndroidComponentPeer (Component* const component, const int windowStyleFlags) | |||
| : ComponentPeer (component, windowStyleFlags), | |||
| view (android.activity.callObjectMethod (android.createNewView, component->isOpaque())), | |||
| view (android.activity.callObjectMethod (JuceAppActivity.createNewView, component->isOpaque())), | |||
| usingAndroidGraphics (false), | |||
| fullScreen (false), | |||
| sizeAllocated (0) | |||
| @@ -48,7 +76,7 @@ public: | |||
| { | |||
| if (MessageManager::getInstance()->isThisTheMessageThread()) | |||
| { | |||
| android.activity.callVoidMethod (android.deleteView, view.get()); | |||
| android.activity.callVoidMethod (JuceAppActivity.deleteView, view.get()); | |||
| } | |||
| else | |||
| { | |||
| @@ -63,7 +91,7 @@ public: | |||
| void messageCallback() | |||
| { | |||
| android.activity.callVoidMethod (android.deleteView, view.get()); | |||
| android.activity.callVoidMethod (JuceAppActivity.deleteView, view.get()); | |||
| } | |||
| private: | |||
| @@ -85,7 +113,7 @@ public: | |||
| { | |||
| if (MessageManager::getInstance()->isThisTheMessageThread()) | |||
| { | |||
| view.callVoidMethod (android.setVisible, shouldBeVisible); | |||
| view.callVoidMethod (ComponentPeerView.setVisible, shouldBeVisible); | |||
| } | |||
| else | |||
| { | |||
| @@ -100,7 +128,7 @@ public: | |||
| void messageCallback() | |||
| { | |||
| view.callVoidMethod (android.setVisible, shouldBeVisible); | |||
| view.callVoidMethod (ComponentPeerView.setVisible, shouldBeVisible); | |||
| } | |||
| private: | |||
| @@ -114,7 +142,7 @@ public: | |||
| void setTitle (const String& title) | |||
| { | |||
| view.callVoidMethod (android.setViewName, javaString (title).get()); | |||
| view.callVoidMethod (ComponentPeerView.setViewName, javaString (title).get()); | |||
| } | |||
| void setPosition (int x, int y) | |||
| @@ -137,7 +165,7 @@ public: | |||
| w = jmax (0, w); | |||
| h = jmax (0, h); | |||
| view.callVoidMethod (android.layout, x, y, x + w, y + h); | |||
| view.callVoidMethod (ComponentPeerView.layout, x, y, x + w, y + h); | |||
| } | |||
| else | |||
| { | |||
| @@ -152,7 +180,7 @@ public: | |||
| void messageCallback() | |||
| { | |||
| view.callVoidMethod (android.layout, x, y, x + w, y + h); | |||
| view.callVoidMethod (ComponentPeerView.layout, x, y, x + w, y + h); | |||
| } | |||
| private: | |||
| @@ -166,16 +194,16 @@ public: | |||
| const Rectangle<int> getBounds() const | |||
| { | |||
| return Rectangle<int> (view.callIntMethod (android.getLeft), | |||
| view.callIntMethod (android.getTop), | |||
| view.callIntMethod (android.getWidth), | |||
| view.callIntMethod (android.getHeight)); | |||
| return Rectangle<int> (view.callIntMethod (ComponentPeerView.getLeft), | |||
| view.callIntMethod (ComponentPeerView.getTop), | |||
| view.callIntMethod (ComponentPeerView.getWidth), | |||
| view.callIntMethod (ComponentPeerView.getHeight)); | |||
| } | |||
| const Point<int> getScreenPosition() const | |||
| { | |||
| return Point<int> (view.callIntMethod (android.getLeft), | |||
| view.callIntMethod (android.getTop)); | |||
| return Point<int> (view.callIntMethod (ComponentPeerView.getLeft), | |||
| view.callIntMethod (ComponentPeerView.getTop)); | |||
| } | |||
| const Point<int> localToGlobal (const Point<int>& relativePosition) | |||
| @@ -227,7 +255,8 @@ public: | |||
| { | |||
| return isPositiveAndBelow (position.getX(), component->getWidth()) | |||
| && isPositiveAndBelow (position.getY(), component->getHeight()) | |||
| && ((! trueIfInAChildWindow) || view.callBooleanMethod (android.containsPoint, position.getX(), position.getY())); | |||
| && ((! trueIfInAChildWindow) || view.callBooleanMethod (ComponentPeerView.containsPoint, | |||
| position.getX(), position.getY())); | |||
| } | |||
| const BorderSize<int> getFrameSize() const | |||
| @@ -244,7 +273,7 @@ public: | |||
| void toFront (bool makeActive) | |||
| { | |||
| view.callVoidMethod (android.bringToFront); | |||
| view.callVoidMethod (ComponentPeerView.bringToFront); | |||
| if (makeActive) | |||
| grabFocus(); | |||
| @@ -283,12 +312,12 @@ public: | |||
| //============================================================================== | |||
| bool isFocused() const | |||
| { | |||
| return view.callBooleanMethod (android.hasFocus); | |||
| return view.callBooleanMethod (ComponentPeerView.hasFocus); | |||
| } | |||
| void grabFocus() | |||
| { | |||
| view.callBooleanMethod (android.requestFocus); | |||
| view.callBooleanMethod (ComponentPeerView.requestFocus); | |||
| } | |||
| void handleFocusChangeCallback (bool hasFocus) | |||
| @@ -307,20 +336,20 @@ public: | |||
| //============================================================================== | |||
| void handlePaintCallback (JNIEnv* env, jobject canvas) | |||
| { | |||
| #if USE_ANDROID_CANVAS | |||
| #if USE_ANDROID_CANVAS | |||
| if (usingAndroidGraphics) | |||
| { | |||
| AndroidLowLevelGraphicsContext g (canvas); | |||
| handlePaint (g); | |||
| } | |||
| else | |||
| #endif | |||
| #endif | |||
| { | |||
| jobject rect = env->CallObjectMethod (canvas, android.getClipBounds2); | |||
| const int left = env->GetIntField (rect, android.rectLeft); | |||
| const int top = env->GetIntField (rect, android.rectTop); | |||
| const int right = env->GetIntField (rect, android.rectRight); | |||
| const int bottom = env->GetIntField (rect, android.rectBottom); | |||
| jobject rect = env->CallObjectMethod (canvas, CanvasMinimal.getClipBounds); | |||
| const int left = env->GetIntField (rect, RectClass.left); | |||
| const int top = env->GetIntField (rect, RectClass.top); | |||
| const int right = env->GetIntField (rect, RectClass.right); | |||
| const int bottom = env->GetIntField (rect, RectClass.bottom); | |||
| env->DeleteLocalRef (rect); | |||
| const Rectangle<int> clip (left, top, right - left, bottom - top); | |||
| @@ -350,7 +379,7 @@ public: | |||
| env->ReleaseIntArrayElements ((jintArray) buffer.get(), dest, 0); | |||
| env->CallVoidMethod (canvas, android.drawMemoryBitmap, (jintArray) buffer.get(), 0, clip.getWidth(), | |||
| env->CallVoidMethod (canvas, CanvasMinimal.drawBitmap, (jintArray) buffer.get(), 0, clip.getWidth(), | |||
| (jfloat) clip.getX(), (jfloat) clip.getY(), | |||
| clip.getWidth(), clip.getHeight(), true, (jobject) 0); | |||
| } | |||
| @@ -361,7 +390,7 @@ public: | |||
| { | |||
| if (MessageManager::getInstance()->isThisTheMessageThread()) | |||
| { | |||
| view.callVoidMethod (android.invalidate, area.getX(), area.getY(), area.getRight(), area.getBottom()); | |||
| view.callVoidMethod (ComponentPeerView.invalidate, area.getX(), area.getY(), area.getRight(), area.getBottom()); | |||
| } | |||
| else | |||
| { | |||
| @@ -376,7 +405,7 @@ public: | |||
| void messageCallback() | |||
| { | |||
| view.callVoidMethod (android.invalidate, area.getX(), area.getY(), area.getRight(), area.getBottom()); | |||
| view.callVoidMethod (ComponentPeerView.invalidate, area.getX(), area.getY(), area.getRight(), area.getBottom()); | |||
| } | |||
| private: | |||
| @@ -511,25 +540,16 @@ Point<int> AndroidComponentPeer::lastMousePos; | |||
| JUCE_JNI_CALLBACK (ComponentPeerView, javaMethodName, returnType, params) \ | |||
| { \ | |||
| AndroidComponentPeer* const peer = AndroidComponentPeer::findPeerForJavaView (view); \ | |||
| if (peer != 0) \ | |||
| if (peer != nullptr) \ | |||
| peer->juceMethodInvocation; \ | |||
| } | |||
| JUCE_VIEW_CALLBACK (void, handlePaint, (JNIEnv* env, jobject view, jobject canvas), | |||
| handlePaintCallback (env, canvas)) | |||
| JUCE_VIEW_CALLBACK (void, handleMouseDown, (JNIEnv*, jobject view, jfloat x, jfloat y, jlong time), | |||
| handleMouseDownCallback ((float) x, (float) y, (int64) time)) | |||
| JUCE_VIEW_CALLBACK (void, handleMouseDrag, (JNIEnv*, jobject view, jfloat x, jfloat y, jlong time), | |||
| handleMouseDragCallback ((float) x, (float) y, (int64) time)) | |||
| JUCE_VIEW_CALLBACK (void, handleMouseUp, (JNIEnv*, jobject view, jfloat x, jfloat y, jlong time), | |||
| handleMouseUpCallback ((float) x, (float) y, (int64) time)) | |||
| JUCE_VIEW_CALLBACK (void, viewSizeChanged, (JNIEnv*, jobject view), | |||
| handleMovedOrResized()) | |||
| JUCE_VIEW_CALLBACK (void, focusChanged, (JNIEnv*, jobject view, jboolean hasFocus), | |||
| handleFocusChangeCallback (hasFocus)) | |||
| JUCE_VIEW_CALLBACK (void, handlePaint, (JNIEnv* env, jobject view, jobject canvas), handlePaintCallback (env, canvas)) | |||
| JUCE_VIEW_CALLBACK (void, handleMouseDown, (JNIEnv*, jobject view, jfloat x, jfloat y, jlong time), handleMouseDownCallback ((float) x, (float) y, (int64) time)) | |||
| JUCE_VIEW_CALLBACK (void, handleMouseDrag, (JNIEnv*, jobject view, jfloat x, jfloat y, jlong time), handleMouseDragCallback ((float) x, (float) y, (int64) time)) | |||
| JUCE_VIEW_CALLBACK (void, handleMouseUp, (JNIEnv*, jobject view, jfloat x, jfloat y, jlong time), handleMouseUpCallback ((float) x, (float) y, (int64) time)) | |||
| JUCE_VIEW_CALLBACK (void, viewSizeChanged, (JNIEnv*, jobject view), handleMovedOrResized()) | |||
| JUCE_VIEW_CALLBACK (void, focusChanged, (JNIEnv*, jobject view, jboolean hasFocus), handleFocusChangeCallback (hasFocus)) | |||
| //============================================================================== | |||
| ComponentPeer* Component::createNewPeer (int styleFlags, void*) | |||
| @@ -596,7 +616,7 @@ void JUCE_CALLTYPE NativeMessageBox::showMessageBoxAsync (AlertWindow::AlertIcon | |||
| const String& title, const String& message, | |||
| Component* associatedComponent) | |||
| { | |||
| android.activity.callVoidMethod (android.showMessageBox, javaString (title).get(), javaString (message).get(), (jlong) 0); | |||
| android.activity.callVoidMethod (JuceAppActivity.showMessageBox, javaString (title).get(), javaString (message).get(), (jlong) 0); | |||
| } | |||
| bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (AlertWindow::AlertIconType iconType, | |||
| @@ -606,7 +626,7 @@ bool JUCE_CALLTYPE NativeMessageBox::showOkCancelBox (AlertWindow::AlertIconType | |||
| { | |||
| jassert (callback != 0); // on android, all alerts must be non-modal!! | |||
| android.activity.callVoidMethod (android.showOkCancelBox, javaString (title).get(), javaString (message).get(), | |||
| android.activity.callVoidMethod (JuceAppActivity.showOkCancelBox, javaString (title).get(), javaString (message).get(), | |||
| (jlong) (pointer_sized_int) callback); | |||
| return false; | |||
| } | |||
| @@ -618,7 +638,7 @@ int JUCE_CALLTYPE NativeMessageBox::showYesNoCancelBox (AlertWindow::AlertIconTy | |||
| { | |||
| jassert (callback != 0); // on android, all alerts must be non-modal!! | |||
| android.activity.callVoidMethod (android.showYesNoCancelBox, javaString (title).get(), javaString (message).get(), | |||
| android.activity.callVoidMethod (JuceAppActivity.showYesNoCancelBox, javaString (title).get(), javaString (message).get(), | |||
| (jlong) (pointer_sized_int) callback); | |||
| return 0; | |||
| } | |||
| @@ -776,6 +776,12 @@ void* threadEntryProc (void* userData) | |||
| JUCE_AUTORELEASEPOOL | |||
| #if JUCE_ANDROID | |||
| struct AndroidThreadScope | |||
| { | |||
| AndroidThreadScope() { threadLocalJNIEnvHolder.attach(); } | |||
| ~AndroidThreadScope() { threadLocalJNIEnvHolder.detach(); } | |||
| }; | |||
| const AndroidThreadScope androidEnv; | |||
| #endif | |||