diff options
| author | Po Lu | 2023-05-29 15:44:14 +0800 |
|---|---|---|
| committer | Po Lu | 2023-05-29 15:44:14 +0800 |
| commit | 00671b18438fec8f2e7f774cb3fd4cd6f694fd18 (patch) | |
| tree | ca4dd77499a73711cced57ddf58c9131bac19706 /java | |
| parent | 327d2d013130ec745880b44573dcda3a6620faba (diff) | |
| download | emacs-00671b18438fec8f2e7f774cb3fd4cd6f694fd18.tar.gz emacs-00671b18438fec8f2e7f774cb3fd4cd6f694fd18.zip | |
Implement android_copy_area in C
* java/org/gnu/emacs/EmacsCopyArea.java: Remove file.
* java/org/gnu/emacs/EmacsService.java (EmacsService, copyArea):
Delete function.
* src/android.c (struct android_emacs_service)
(android_init_emacs_service): Remove `copy_area'.
(android_create_gc, android_change_gc, android_get_gc_values):
Record new GC values.
(android_neon_mask_line): New function.
(android_blit_copy, android_blit_xor): New functions.
(android_copy_area): Implement in C.
(android_lock_bitmap): Accept drawables instead of windows.
* src/android.h: Adjust prototype for `android_lock_bitmap'.
* src/androidgui.h (struct android_gc): Record last known GC
values.
Diffstat (limited to 'java')
| -rw-r--r-- | java/org/gnu/emacs/EmacsCopyArea.java | 206 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsService.java | 12 |
2 files changed, 0 insertions, 218 deletions
diff --git a/java/org/gnu/emacs/EmacsCopyArea.java b/java/org/gnu/emacs/EmacsCopyArea.java deleted file mode 100644 index f69b0cde866..00000000000 --- a/java/org/gnu/emacs/EmacsCopyArea.java +++ /dev/null | |||
| @@ -1,206 +0,0 @@ | |||
| 1 | /* Communication module for Android terminals. -*- c-file-style: "GNU" -*- | ||
| 2 | |||
| 3 | Copyright (C) 2023 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | This file is part of GNU Emacs. | ||
| 6 | |||
| 7 | GNU Emacs is free software: you can redistribute it and/or modify | ||
| 8 | it under the terms of the GNU General Public License as published by | ||
| 9 | the Free Software Foundation, either version 3 of the License, or (at | ||
| 10 | your option) any later version. | ||
| 11 | |||
| 12 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | ||
| 19 | |||
| 20 | package org.gnu.emacs; | ||
| 21 | |||
| 22 | import android.graphics.Bitmap; | ||
| 23 | import android.graphics.Canvas; | ||
| 24 | import android.graphics.Paint; | ||
| 25 | import android.graphics.PorterDuff.Mode; | ||
| 26 | import android.graphics.PorterDuffXfermode; | ||
| 27 | import android.graphics.Rect; | ||
| 28 | import android.graphics.Xfermode; | ||
| 29 | |||
| 30 | public final class EmacsCopyArea | ||
| 31 | { | ||
| 32 | private static Xfermode overAlu; | ||
| 33 | |||
| 34 | static | ||
| 35 | { | ||
| 36 | overAlu = new PorterDuffXfermode (Mode.SRC_OVER); | ||
| 37 | }; | ||
| 38 | |||
| 39 | private static void | ||
| 40 | insetRectBy (Rect rect, int left, int top, int right, | ||
| 41 | int bottom) | ||
| 42 | { | ||
| 43 | rect.left += left; | ||
| 44 | rect.top += top; | ||
| 45 | rect.right -= right; | ||
| 46 | rect.bottom -= bottom; | ||
| 47 | } | ||
| 48 | |||
| 49 | public static void | ||
| 50 | perform (EmacsDrawable source, EmacsGC gc, | ||
| 51 | EmacsDrawable destination, | ||
| 52 | int src_x, int src_y, int width, int height, | ||
| 53 | int dest_x, int dest_y) | ||
| 54 | { | ||
| 55 | int i; | ||
| 56 | Bitmap bitmap; | ||
| 57 | Paint maskPaint, paint; | ||
| 58 | Canvas maskCanvas, canvas; | ||
| 59 | Bitmap srcBitmap, maskBitmap, clipBitmap; | ||
| 60 | Rect rect, maskRect, srcRect, dstRect, maskDestRect; | ||
| 61 | boolean needFill; | ||
| 62 | |||
| 63 | /* TODO implement stippling. */ | ||
| 64 | if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED) | ||
| 65 | return; | ||
| 66 | |||
| 67 | paint = gc.gcPaint; | ||
| 68 | |||
| 69 | canvas = destination.lockCanvas (gc); | ||
| 70 | |||
| 71 | if (canvas == null) | ||
| 72 | return; | ||
| 73 | |||
| 74 | /* A copy must be created or drawBitmap could end up overwriting | ||
| 75 | itself. */ | ||
| 76 | srcBitmap = source.getBitmap (); | ||
| 77 | |||
| 78 | /* If srcBitmap is out of bounds, then adjust the source rectangle | ||
| 79 | to be within bounds. Note that tiling on windows with | ||
| 80 | backgrounds is unimplemented. */ | ||
| 81 | |||
| 82 | if (src_x < 0) | ||
| 83 | { | ||
| 84 | width += src_x; | ||
| 85 | dest_x -= src_x; | ||
| 86 | src_x = 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | if (src_y < 0) | ||
| 90 | { | ||
| 91 | height += src_y; | ||
| 92 | dest_y -= src_y; | ||
| 93 | src_y = 0; | ||
| 94 | } | ||
| 95 | |||
| 96 | if (src_x + width > srcBitmap.getWidth ()) | ||
| 97 | width = srcBitmap.getWidth () - src_x; | ||
| 98 | |||
| 99 | if (src_y + height > srcBitmap.getHeight ()) | ||
| 100 | height = srcBitmap.getHeight () - src_y; | ||
| 101 | |||
| 102 | /* If width and height are empty or negative, then skip the entire | ||
| 103 | CopyArea operation lest createBitmap throw an exception. */ | ||
| 104 | |||
| 105 | if (width <= 0 || height <= 0) | ||
| 106 | return; | ||
| 107 | |||
| 108 | rect = new Rect (dest_x, dest_y, dest_x + width, | ||
| 109 | dest_y + height); | ||
| 110 | |||
| 111 | if (gc.clip_mask == null) | ||
| 112 | { | ||
| 113 | if (source == destination) | ||
| 114 | { | ||
| 115 | /* Create a copy of the bitmap, since Android can't handle | ||
| 116 | overlapping copies. */ | ||
| 117 | bitmap = Bitmap.createBitmap (srcBitmap, | ||
| 118 | src_x, src_y, width, | ||
| 119 | height); | ||
| 120 | canvas.drawBitmap (bitmap, null, rect, paint); | ||
| 121 | bitmap.recycle (); | ||
| 122 | } | ||
| 123 | else | ||
| 124 | { | ||
| 125 | /* But here the bitmaps are known to not overlap, so avoid | ||
| 126 | that extra consing overhead. */ | ||
| 127 | |||
| 128 | srcRect = new Rect (src_x, src_y, src_x + width, | ||
| 129 | src_y + height); | ||
| 130 | canvas.drawBitmap (srcBitmap, srcRect, rect, paint); | ||
| 131 | } | ||
| 132 | } | ||
| 133 | else | ||
| 134 | { | ||
| 135 | /* Drawing with a clip mask involves calculating the | ||
| 136 | intersection of the clip mask with the dst rect, and | ||
| 137 | extrapolating the corresponding part of the src rect. */ | ||
| 138 | clipBitmap = gc.clip_mask.bitmap; | ||
| 139 | dstRect = new Rect (dest_x, dest_y, | ||
| 140 | dest_x + width, | ||
| 141 | dest_y + height); | ||
| 142 | maskRect = new Rect (gc.clip_x_origin, | ||
| 143 | gc.clip_y_origin, | ||
| 144 | (gc.clip_x_origin | ||
| 145 | + clipBitmap.getWidth ()), | ||
| 146 | (gc.clip_y_origin | ||
| 147 | + clipBitmap.getHeight ())); | ||
| 148 | clipBitmap = gc.clip_mask.bitmap; | ||
| 149 | |||
| 150 | if (!maskRect.setIntersect (dstRect, maskRect)) | ||
| 151 | /* There is no intersection between the clip mask and the | ||
| 152 | dest rect. */ | ||
| 153 | return; | ||
| 154 | |||
| 155 | /* Now figure out which part of the source corresponds to | ||
| 156 | maskRect and return it relative to srcBitmap. */ | ||
| 157 | srcRect = new Rect (src_x, src_y, src_x + width, | ||
| 158 | src_y + height); | ||
| 159 | insetRectBy (srcRect, maskRect.left - dstRect.left, | ||
| 160 | maskRect.top - dstRect.top, | ||
| 161 | maskRect.right - dstRect.right, | ||
| 162 | maskRect.bottom - dstRect.bottom); | ||
| 163 | |||
| 164 | /* Finally, create a temporary bitmap that is the size of | ||
| 165 | maskRect. */ | ||
| 166 | |||
| 167 | maskBitmap | ||
| 168 | = Bitmap.createBitmap (maskRect.width (), maskRect.height (), | ||
| 169 | Bitmap.Config.ARGB_8888); | ||
| 170 | |||
| 171 | /* Draw the mask onto the maskBitmap. */ | ||
| 172 | maskCanvas = new Canvas (maskBitmap); | ||
| 173 | maskPaint = new Paint (); | ||
| 174 | maskRect.offset (-gc.clip_x_origin, | ||
| 175 | -gc.clip_y_origin); | ||
| 176 | maskCanvas.drawBitmap (gc.clip_mask.bitmap, | ||
| 177 | maskRect, | ||
| 178 | new Rect (0, 0, | ||
| 179 | maskRect.width (), | ||
| 180 | maskRect.height ()), | ||
| 181 | maskPaint); | ||
| 182 | maskRect.offset (gc.clip_x_origin, | ||
| 183 | gc.clip_y_origin); | ||
| 184 | |||
| 185 | /* Set the transfer mode to SRC_IN to preserve only the parts | ||
| 186 | of the source that overlap with the mask. */ | ||
| 187 | maskPaint.setXfermode (EmacsGC.srcInAlu); | ||
| 188 | |||
| 189 | /* Draw the source. */ | ||
| 190 | maskDestRect = new Rect (0, 0, srcRect.width (), | ||
| 191 | srcRect.height ()); | ||
| 192 | maskCanvas.drawBitmap (srcBitmap, srcRect, maskDestRect, | ||
| 193 | maskPaint); | ||
| 194 | |||
| 195 | /* Finally, draw the mask bitmap to the destination. */ | ||
| 196 | paint.setXfermode (overAlu); | ||
| 197 | canvas.drawBitmap (maskBitmap, null, maskRect, paint); | ||
| 198 | gc.resetXfermode (); | ||
| 199 | |||
| 200 | /* Recycle this unused bitmap. */ | ||
| 201 | maskBitmap.recycle (); | ||
| 202 | } | ||
| 203 | |||
| 204 | destination.damageRect (rect); | ||
| 205 | } | ||
| 206 | } | ||
diff --git a/java/org/gnu/emacs/EmacsService.java b/java/org/gnu/emacs/EmacsService.java index d2e52ed5e62..546d22627c5 100644 --- a/java/org/gnu/emacs/EmacsService.java +++ b/java/org/gnu/emacs/EmacsService.java | |||
| @@ -375,18 +375,6 @@ public final class EmacsService extends Service | |||
| 375 | } | 375 | } |
| 376 | 376 | ||
| 377 | public void | 377 | public void |
| 378 | copyArea (EmacsDrawable srcDrawable, EmacsDrawable dstDrawable, | ||
| 379 | EmacsGC gc, | ||
| 380 | int srcX, int srcY, int width, int height, int destX, | ||
| 381 | int destY) | ||
| 382 | { | ||
| 383 | checkEmacsThread (); | ||
| 384 | EmacsCopyArea.perform (srcDrawable, gc, dstDrawable, | ||
| 385 | srcX, srcY, width, height, destX, | ||
| 386 | destY); | ||
| 387 | } | ||
| 388 | |||
| 389 | public void | ||
| 390 | clearWindow (EmacsWindow window) | 378 | clearWindow (EmacsWindow window) |
| 391 | { | 379 | { |
| 392 | checkEmacsThread (); | 380 | checkEmacsThread (); |