diff options
| author | Po Lu | 2023-05-29 17:46:19 +0800 |
|---|---|---|
| committer | Po Lu | 2023-05-29 17:46:19 +0800 |
| commit | 7fdde02f3216536aa8977fa4b396bec8fbaf994b (patch) | |
| tree | 6f38d0cdc45f5cd50343d48f4028febe8b397251 | |
| parent | 9a3535459333b5a1a32ed5b5ef4c593e585bfe9a (diff) | |
| download | emacs-7fdde02f3216536aa8977fa4b396bec8fbaf994b.tar.gz emacs-7fdde02f3216536aa8977fa4b396bec8fbaf994b.zip | |
Work around more problems with Bitmaps
* java/org/gnu/emacs/EmacsNative.java (EmacsNative): New
function `blitRect'.
* java/org/gnu/emacs/EmacsSurfaceView.java (EmacsSurfaceView):
Use it on Android 8.x.
* src/android.c (blitRect): Implement new function.
| -rw-r--r-- | java/org/gnu/emacs/EmacsNative.java | 10 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsSurfaceView.java | 33 | ||||
| -rw-r--r-- | src/android.c | 98 |
3 files changed, 137 insertions, 4 deletions
diff --git a/java/org/gnu/emacs/EmacsNative.java b/java/org/gnu/emacs/EmacsNative.java index e699dda9ad4..56c03ee38dc 100644 --- a/java/org/gnu/emacs/EmacsNative.java +++ b/java/org/gnu/emacs/EmacsNative.java | |||
| @@ -20,6 +20,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 20 | package org.gnu.emacs; | 20 | package org.gnu.emacs; |
| 21 | 21 | ||
| 22 | import android.content.res.AssetManager; | 22 | import android.content.res.AssetManager; |
| 23 | |||
| 24 | import android.graphics.Bitmap; | ||
| 25 | |||
| 23 | import android.view.inputmethod.ExtractedText; | 26 | import android.view.inputmethod.ExtractedText; |
| 24 | import android.view.inputmethod.ExtractedTextRequest; | 27 | import android.view.inputmethod.ExtractedTextRequest; |
| 25 | 28 | ||
| @@ -216,6 +219,13 @@ public final class EmacsNative | |||
| 216 | failure. */ | 219 | failure. */ |
| 217 | public static native int[] getSelection (short window); | 220 | public static native int[] getSelection (short window); |
| 218 | 221 | ||
| 222 | |||
| 223 | /* Graphics functions used as a replacement for potentially buggy | ||
| 224 | Android APIs. */ | ||
| 225 | |||
| 226 | public static native void blitRect (Bitmap src, Bitmap dest, int x1, | ||
| 227 | int y1, int x2, int y2); | ||
| 228 | |||
| 219 | static | 229 | static |
| 220 | { | 230 | { |
| 221 | /* Older versions of Android cannot link correctly with shared | 231 | /* Older versions of Android cannot link correctly with shared |
diff --git a/java/org/gnu/emacs/EmacsSurfaceView.java b/java/org/gnu/emacs/EmacsSurfaceView.java index e0411f7f8b3..0deb930c2c2 100644 --- a/java/org/gnu/emacs/EmacsSurfaceView.java +++ b/java/org/gnu/emacs/EmacsSurfaceView.java | |||
| @@ -57,11 +57,36 @@ public final class EmacsSurfaceView extends View | |||
| 57 | private void | 57 | private void |
| 58 | copyToFrontBuffer (Bitmap bitmap, Rect damageRect) | 58 | copyToFrontBuffer (Bitmap bitmap, Rect damageRect) |
| 59 | { | 59 | { |
| 60 | if (damageRect != null) | 60 | EmacsService.checkEmacsThread (); |
| 61 | bitmapCanvas.drawBitmap (bitmap, damageRect, damageRect, | 61 | |
| 62 | bitmapPaint); | 62 | if (Build.VERSION.SDK_INT != Build.VERSION_CODES.O |
| 63 | && Build.VERSION.SDK_INT != Build.VERSION_CODES.O_MR1) | ||
| 64 | { | ||
| 65 | /* If `drawBitmap' can safely be used while a bitmap is locked | ||
| 66 | by another thread, continue here... */ | ||
| 67 | |||
| 68 | if (damageRect != null) | ||
| 69 | bitmapCanvas.drawBitmap (bitmap, damageRect, damageRect, | ||
| 70 | bitmapPaint); | ||
| 71 | else | ||
| 72 | bitmapCanvas.drawBitmap (bitmap, 0f, 0f, bitmapPaint); | ||
| 73 | } | ||
| 63 | else | 74 | else |
| 64 | bitmapCanvas.drawBitmap (bitmap, 0f, 0f, bitmapPaint); | 75 | { |
| 76 | /* But if it can not, as on Android 8.0 and 8.1, then use a | ||
| 77 | replacement function. */ | ||
| 78 | |||
| 79 | if (damageRect != null) | ||
| 80 | EmacsNative.blitRect (bitmap, frontBuffer, | ||
| 81 | damageRect.left, | ||
| 82 | damageRect.top, | ||
| 83 | damageRect.right, | ||
| 84 | damageRect.bottom); | ||
| 85 | else | ||
| 86 | EmacsNative.blitRect (bitmap, frontBuffer, 0, 0, | ||
| 87 | bitmap.getWidth (), | ||
| 88 | bitmap.getHeight ()); | ||
| 89 | } | ||
| 65 | } | 90 | } |
| 66 | 91 | ||
| 67 | private void | 92 | private void |
diff --git a/src/android.c b/src/android.c index 7b9c478f212..4184be3086b 100644 --- a/src/android.c +++ b/src/android.c | |||
| @@ -4754,6 +4754,104 @@ android_copy_area (android_drawable src, android_drawable dest, | |||
| 4754 | 4754 | ||
| 4755 | 4755 | ||
| 4756 | 4756 | ||
| 4757 | JNIEXPORT void JNICALL | ||
| 4758 | NATIVE_NAME (blitRect) (JNIEnv *env, jobject object, | ||
| 4759 | jobject src, jobject dest, | ||
| 4760 | jint x1, jint y1, jint x2, jint y2) | ||
| 4761 | { | ||
| 4762 | AndroidBitmapInfo src_info, dest_info; | ||
| 4763 | unsigned char *src_data_1, *dest_data_1; | ||
| 4764 | void *src_data, *dest_data; | ||
| 4765 | |||
| 4766 | /* N.B. that X2 and Y2 represent the pixel past the edge of the | ||
| 4767 | rectangle; thus, the width is x2 - x1 and the height is y2 - | ||
| 4768 | y1. */ | ||
| 4769 | |||
| 4770 | memset (&src_info, 0, sizeof src_info); | ||
| 4771 | memset (&dest_info, 0, sizeof dest_info); | ||
| 4772 | AndroidBitmap_getInfo (env, src, &src_info); | ||
| 4773 | AndroidBitmap_getInfo (env, dest, &dest_info); | ||
| 4774 | |||
| 4775 | /* If the stride is 0 after a call to `getInfo', assume it | ||
| 4776 | failed. */ | ||
| 4777 | |||
| 4778 | if (!src_info.stride || !dest_info.stride) | ||
| 4779 | return; | ||
| 4780 | |||
| 4781 | /* If formats differ, abort. */ | ||
| 4782 | eassert (src_info.format == dest_info.format | ||
| 4783 | && src_info.format == ANDROID_BITMAP_FORMAT_RGBA_8888); | ||
| 4784 | |||
| 4785 | /* Lock the image data. */ | ||
| 4786 | src_data = NULL; | ||
| 4787 | AndroidBitmap_lockPixels (env, src, &src_data); | ||
| 4788 | |||
| 4789 | if (!src_data) | ||
| 4790 | return; | ||
| 4791 | |||
| 4792 | dest_data = NULL; | ||
| 4793 | AndroidBitmap_lockPixels (env, dest, &dest_data); | ||
| 4794 | |||
| 4795 | if (!dest_data) | ||
| 4796 | goto fail1; | ||
| 4797 | |||
| 4798 | /* Now clip the rectangle to the bounds of the source and | ||
| 4799 | destination bitmap. */ | ||
| 4800 | |||
| 4801 | x1 = MAX (x1, 0); | ||
| 4802 | y1 = MAX (y1, 0); | ||
| 4803 | x2 = MAX (x2, 0); | ||
| 4804 | y2 = MAX (y2, 0); | ||
| 4805 | |||
| 4806 | |||
| 4807 | if (x1 >= src_info.width | ||
| 4808 | || x1 >= dest_info.width) | ||
| 4809 | x1 = MIN (dest_info.width - 1, src_info.width - 1); | ||
| 4810 | |||
| 4811 | if (x2 > src_info.width | ||
| 4812 | || x2 > dest_info.width) | ||
| 4813 | x2 = MIN (src_info.width, dest_info.width); | ||
| 4814 | |||
| 4815 | if (y1 >= src_info.height | ||
| 4816 | || y1 >= dest_info.height) | ||
| 4817 | y1 = MIN (dest_info.height - 1, src_info.height - 1); | ||
| 4818 | |||
| 4819 | if (y2 > src_info.height | ||
| 4820 | || y2 > dest_info.height) | ||
| 4821 | y2 = MIN (src_info.height, dest_info.height); | ||
| 4822 | |||
| 4823 | if (x1 >= x2 || y1 >= y2) | ||
| 4824 | goto fail2; | ||
| 4825 | |||
| 4826 | /* Determine the address of the first line to copy. */ | ||
| 4827 | |||
| 4828 | src_data_1 = src_data; | ||
| 4829 | dest_data_1 = dest_data; | ||
| 4830 | src_data_1 += x1 * 4; | ||
| 4831 | src_data_1 += y1 * src_info.stride; | ||
| 4832 | dest_data_1 += x1 * 4; | ||
| 4833 | dest_data_1 += y1 * dest_info.stride; | ||
| 4834 | |||
| 4835 | /* Start copying each line. */ | ||
| 4836 | |||
| 4837 | while (y1 != y2) | ||
| 4838 | { | ||
| 4839 | memcpy (dest_data_1, src_data_1, (x2 - x1) * 4); | ||
| 4840 | src_data_1 += src_info.stride; | ||
| 4841 | dest_data_1 += dest_info.stride; | ||
| 4842 | y1++; | ||
| 4843 | } | ||
| 4844 | |||
| 4845 | /* Complete the copy and unlock the bitmap. */ | ||
| 4846 | |||
| 4847 | fail2: | ||
| 4848 | AndroidBitmap_unlockPixels (env, dest); | ||
| 4849 | fail1: | ||
| 4850 | AndroidBitmap_unlockPixels (env, src); | ||
| 4851 | } | ||
| 4852 | |||
| 4853 | |||
| 4854 | |||
| 4757 | void | 4855 | void |
| 4758 | android_free_pixmap (android_pixmap pixmap) | 4856 | android_free_pixmap (android_pixmap pixmap) |
| 4759 | { | 4857 | { |