diff options
| author | Po Lu | 2024-05-02 11:31:37 +0800 |
|---|---|---|
| committer | Po Lu | 2024-05-02 11:31:37 +0800 |
| commit | b84fa71f8985284560bacda7d407e3559583844f (patch) | |
| tree | d7ed4518760fe51795dce384bc9dfa0b4ed32faf | |
| parent | d3e95fcae9078a0ea8fcb15a4aee417e6e546ee5 (diff) | |
| download | emacs-b84fa71f8985284560bacda7d407e3559583844f.tar.gz emacs-b84fa71f8985284560bacda7d407e3559583844f.zip | |
Port visible bell to Android
* java/org/gnu/emacs/EmacsDrawRectangle.java (perform): Ignore
GC_INVERT.
* java/org/gnu/emacs/EmacsFillRectangle.java
(EmacsFillRectangle) <invertFilter>: New variable.
(perform): If the transfer mode is invert, copy the source
to itself with invertFilter as the color filter.
* java/org/gnu/emacs/EmacsGC.java (EmacsGC) <xorAlu, srcInAlu>:
Delete now-redundant ALUs.
(markDirty): Cease updating the paint's transfermode.
* java/org/gnu/emacs/EmacsSafThread.java (openDocument1): Fix
typo in documentation.
* src/android.c (android_blit_xor): Delete unused function.
(android_copy_area): Remove calls to unused blit functions.
* src/androidgui.h (enum android_gc_function): Rename XOR to
INVERT.
* src/androidterm.c (android_flash): Replace with GXinvert.
| -rw-r--r-- | java/org/gnu/emacs/EmacsDrawRectangle.java | 18 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsFillRectangle.java | 96 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsGC.java | 16 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsSafThread.java | 8 | ||||
| -rw-r--r-- | src/android.c | 288 | ||||
| -rw-r--r-- | src/androidgui.h | 2 | ||||
| -rw-r--r-- | src/androidterm.c | 10 |
7 files changed, 63 insertions, 375 deletions
diff --git a/java/org/gnu/emacs/EmacsDrawRectangle.java b/java/org/gnu/emacs/EmacsDrawRectangle.java index e40a7c16068..ea0f1c28106 100644 --- a/java/org/gnu/emacs/EmacsDrawRectangle.java +++ b/java/org/gnu/emacs/EmacsDrawRectangle.java | |||
| @@ -22,13 +22,23 @@ package org.gnu.emacs; | |||
| 22 | import android.graphics.Bitmap; | 22 | import android.graphics.Bitmap; |
| 23 | import android.graphics.Canvas; | 23 | import android.graphics.Canvas; |
| 24 | import android.graphics.Paint; | 24 | import android.graphics.Paint; |
| 25 | import android.graphics.PorterDuff.Mode; | ||
| 26 | import android.graphics.PorterDuffXfermode; | ||
| 25 | import android.graphics.Rect; | 27 | import android.graphics.Rect; |
| 26 | import android.graphics.RectF; | 28 | import android.graphics.RectF; |
| 29 | import android.graphics.Xfermode; | ||
| 27 | 30 | ||
| 28 | import android.util.Log; | 31 | import android.util.Log; |
| 29 | 32 | ||
| 30 | public final class EmacsDrawRectangle | 33 | public final class EmacsDrawRectangle |
| 31 | { | 34 | { |
| 35 | private static final Xfermode srcInAlu; | ||
| 36 | |||
| 37 | static | ||
| 38 | { | ||
| 39 | srcInAlu = new PorterDuffXfermode (Mode.SRC_IN); | ||
| 40 | }; | ||
| 41 | |||
| 32 | public static void | 42 | public static void |
| 33 | perform (EmacsDrawable drawable, EmacsGC gc, | 43 | perform (EmacsDrawable drawable, EmacsGC gc, |
| 34 | int x, int y, int width, int height) | 44 | int x, int y, int width, int height) |
| @@ -40,8 +50,10 @@ public final class EmacsDrawRectangle | |||
| 40 | Canvas canvas; | 50 | Canvas canvas; |
| 41 | Bitmap clipBitmap; | 51 | Bitmap clipBitmap; |
| 42 | 52 | ||
| 43 | /* TODO implement stippling. */ | 53 | /* TODO implement stippling for this request. */ |
| 44 | if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED) | 54 | if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED |
| 55 | /* And GC_INVERT also. */ | ||
| 56 | || gc.fill_style == EmacsGC.GC_INVERT) | ||
| 45 | return; | 57 | return; |
| 46 | 58 | ||
| 47 | canvas = drawable.lockCanvas (gc); | 59 | canvas = drawable.lockCanvas (gc); |
| @@ -103,7 +115,7 @@ public final class EmacsDrawRectangle | |||
| 103 | /* Set the transfer mode to SRC_IN to preserve only the parts | 115 | /* Set the transfer mode to SRC_IN to preserve only the parts |
| 104 | of the source that overlap with the mask. */ | 116 | of the source that overlap with the mask. */ |
| 105 | maskPaint = new Paint (); | 117 | maskPaint = new Paint (); |
| 106 | maskPaint.setXfermode (EmacsGC.srcInAlu); | 118 | maskPaint.setXfermode (srcInAlu); |
| 107 | maskPaint.setStyle (Paint.Style.STROKE); | 119 | maskPaint.setStyle (Paint.Style.STROKE); |
| 108 | 120 | ||
| 109 | /* Draw the source. */ | 121 | /* Draw the source. */ |
diff --git a/java/org/gnu/emacs/EmacsFillRectangle.java b/java/org/gnu/emacs/EmacsFillRectangle.java index f338a54f97b..7642deed7c3 100644 --- a/java/org/gnu/emacs/EmacsFillRectangle.java +++ b/java/org/gnu/emacs/EmacsFillRectangle.java | |||
| @@ -21,6 +21,8 @@ package org.gnu.emacs; | |||
| 21 | 21 | ||
| 22 | import android.graphics.Bitmap; | 22 | import android.graphics.Bitmap; |
| 23 | import android.graphics.Canvas; | 23 | import android.graphics.Canvas; |
| 24 | import android.graphics.ColorFilter; | ||
| 25 | import android.graphics.ColorMatrixColorFilter; | ||
| 24 | import android.graphics.Paint; | 26 | import android.graphics.Paint; |
| 25 | import android.graphics.Rect; | 27 | import android.graphics.Rect; |
| 26 | 28 | ||
| @@ -28,30 +30,42 @@ import android.util.Log; | |||
| 28 | 30 | ||
| 29 | public final class EmacsFillRectangle | 31 | public final class EmacsFillRectangle |
| 30 | { | 32 | { |
| 33 | /* Color filter that inverts colors from the source. */ | ||
| 34 | private static final ColorFilter invertFilter; | ||
| 35 | |||
| 36 | static | ||
| 37 | { | ||
| 38 | invertFilter = new ColorMatrixColorFilter (new float[] { | ||
| 39 | -1f, 0f, 0f, 0f, 255f, | ||
| 40 | 0f, -1f, 0f, 0f, 255f, | ||
| 41 | 0f, 0f, -1f, 0f, 255f, | ||
| 42 | 0f, 0f, 0f, 1f, 0f, | ||
| 43 | }); | ||
| 44 | }; | ||
| 45 | |||
| 31 | public static void | 46 | public static void |
| 32 | perform (EmacsDrawable drawable, EmacsGC gc, | 47 | perform (EmacsDrawable drawable, EmacsGC gc, |
| 33 | int x, int y, int width, int height) | 48 | int x, int y, int width, int height) |
| 34 | { | 49 | { |
| 35 | Paint maskPaint, paint; | 50 | Paint paint; |
| 36 | Canvas maskCanvas; | ||
| 37 | Bitmap maskBitmap; | ||
| 38 | Rect rect; | 51 | Rect rect; |
| 39 | Rect maskRect, dstRect; | ||
| 40 | Canvas canvas; | 52 | Canvas canvas; |
| 41 | Bitmap clipBitmap; | 53 | Bitmap invertBitmap; |
| 42 | 54 | ||
| 43 | canvas = drawable.lockCanvas (gc); | 55 | canvas = drawable.lockCanvas (gc); |
| 44 | 56 | ||
| 45 | if (canvas == null) | 57 | /* Clip masks are not respected or implemented when specified with |
| 58 | this request. */ | ||
| 59 | if (canvas == null || gc.clip_mask != null) | ||
| 46 | return; | 60 | return; |
| 47 | 61 | ||
| 48 | rect = new Rect (x, y, x + width, y + height); | 62 | rect = new Rect (x, y, x + width, y + height); |
| 49 | 63 | ||
| 50 | paint = gc.gcPaint; | 64 | if (gc.function != EmacsGC.GC_INVERT) |
| 51 | paint.setStyle (Paint.Style.FILL); | ||
| 52 | |||
| 53 | if (gc.clip_mask == null) | ||
| 54 | { | 65 | { |
| 66 | paint = gc.gcPaint; | ||
| 67 | paint.setStyle (Paint.Style.FILL); | ||
| 68 | |||
| 55 | if (gc.fill_style != EmacsGC.GC_FILL_OPAQUE_STIPPLED) | 69 | if (gc.fill_style != EmacsGC.GC_FILL_OPAQUE_STIPPLED) |
| 56 | canvas.drawRect (rect, paint); | 70 | canvas.drawRect (rect, paint); |
| 57 | else | 71 | else |
| @@ -59,57 +73,17 @@ public final class EmacsFillRectangle | |||
| 59 | } | 73 | } |
| 60 | else | 74 | else |
| 61 | { | 75 | { |
| 62 | /* Drawing with a clip mask involves calculating the | 76 | paint = new Paint (); |
| 63 | intersection of the clip mask with the dst rect, and | 77 | |
| 64 | extrapolating the corresponding part of the src rect. */ | 78 | /* Simply invert the destination, which is only implemented for |
| 65 | 79 | this request. As Android doesn't permit copying a bitmap to | |
| 66 | clipBitmap = gc.clip_mask.bitmap; | 80 | itself, a copy of the source must be procured beforehand. */ |
| 67 | dstRect = new Rect (x, y, x + width, y + height); | 81 | invertBitmap = Bitmap.createBitmap (drawable.getBitmap (), |
| 68 | maskRect = new Rect (gc.clip_x_origin, | 82 | x, y, width, height); |
| 69 | gc.clip_y_origin, | 83 | paint.setColorFilter (invertFilter); |
| 70 | (gc.clip_x_origin | 84 | canvas.drawBitmap (invertBitmap, null, rect, paint); |
| 71 | + clipBitmap.getWidth ()), | 85 | paint.setColorFilter (null); |
| 72 | (gc.clip_y_origin | 86 | invertBitmap.recycle (); |
| 73 | + clipBitmap.getHeight ())); | ||
| 74 | |||
| 75 | if (!maskRect.setIntersect (dstRect, maskRect)) | ||
| 76 | /* There is no intersection between the clip mask and the | ||
| 77 | dest rect. */ | ||
| 78 | return; | ||
| 79 | |||
| 80 | /* Finally, create a temporary bitmap that is the size of | ||
| 81 | maskRect. */ | ||
| 82 | |||
| 83 | maskBitmap | ||
| 84 | = Bitmap.createBitmap (maskRect.width (), maskRect.height (), | ||
| 85 | Bitmap.Config.ARGB_8888); | ||
| 86 | |||
| 87 | /* Draw the mask onto the maskBitmap. */ | ||
| 88 | maskCanvas = new Canvas (maskBitmap); | ||
| 89 | maskRect.offset (-gc.clip_x_origin, | ||
| 90 | -gc.clip_y_origin); | ||
| 91 | maskCanvas.drawBitmap (gc.clip_mask.bitmap, | ||
| 92 | maskRect, new Rect (0, 0, | ||
| 93 | maskRect.width (), | ||
| 94 | maskRect.height ()), | ||
| 95 | paint); | ||
| 96 | maskRect.offset (gc.clip_x_origin, | ||
| 97 | gc.clip_y_origin); | ||
| 98 | |||
| 99 | /* Set the transfer mode to SRC_IN to preserve only the parts | ||
| 100 | of the source that overlap with the mask. */ | ||
| 101 | maskPaint = new Paint (); | ||
| 102 | maskPaint.setXfermode (EmacsGC.srcInAlu); | ||
| 103 | |||
| 104 | /* Draw the source. */ | ||
| 105 | maskCanvas.drawRect (maskRect, maskPaint); | ||
| 106 | |||
| 107 | /* Finally, draw the mask bitmap to the destination. */ | ||
| 108 | paint.setXfermode (null); | ||
| 109 | canvas.drawBitmap (maskBitmap, null, maskRect, paint); | ||
| 110 | |||
| 111 | /* Recycle this unused bitmap. */ | ||
| 112 | maskBitmap.recycle (); | ||
| 113 | } | 87 | } |
| 114 | 88 | ||
| 115 | drawable.damageRect (rect); | 89 | drawable.damageRect (rect); |
diff --git a/java/org/gnu/emacs/EmacsGC.java b/java/org/gnu/emacs/EmacsGC.java index ec2b9c9e475..bb11f76c800 100644 --- a/java/org/gnu/emacs/EmacsGC.java +++ b/java/org/gnu/emacs/EmacsGC.java | |||
| @@ -27,9 +27,7 @@ import android.graphics.Canvas; | |||
| 27 | import android.graphics.ColorFilter; | 27 | import android.graphics.ColorFilter; |
| 28 | import android.graphics.PorterDuff.Mode; | 28 | import android.graphics.PorterDuff.Mode; |
| 29 | import android.graphics.PorterDuffColorFilter; | 29 | import android.graphics.PorterDuffColorFilter; |
| 30 | import android.graphics.PorterDuffXfermode; | ||
| 31 | import android.graphics.Shader.TileMode; | 30 | import android.graphics.Shader.TileMode; |
| 32 | import android.graphics.Xfermode; | ||
| 33 | 31 | ||
| 34 | import android.graphics.drawable.BitmapDrawable; | 32 | import android.graphics.drawable.BitmapDrawable; |
| 35 | 33 | ||
| @@ -40,8 +38,8 @@ import android.os.Build; | |||
| 40 | 38 | ||
| 41 | public final class EmacsGC extends EmacsHandleObject | 39 | public final class EmacsGC extends EmacsHandleObject |
| 42 | { | 40 | { |
| 43 | public static final int GC_COPY = 0; | 41 | public static final int GC_COPY = 0; |
| 44 | public static final int GC_XOR = 1; | 42 | public static final int GC_INVERT = 1; |
| 45 | 43 | ||
| 46 | public static final int GC_FILL_SOLID = 0; | 44 | public static final int GC_FILL_SOLID = 0; |
| 47 | public static final int GC_FILL_OPAQUE_STIPPLED = 1; | 45 | public static final int GC_FILL_OPAQUE_STIPPLED = 1; |
| @@ -49,8 +47,6 @@ public final class EmacsGC extends EmacsHandleObject | |||
| 49 | public static final int GC_LINE_SOLID = 0; | 47 | public static final int GC_LINE_SOLID = 0; |
| 50 | public static final int GC_LINE_ON_OFF_DASH = 1; | 48 | public static final int GC_LINE_ON_OFF_DASH = 1; |
| 51 | 49 | ||
| 52 | public static final Xfermode xorAlu, srcInAlu; | ||
| 53 | |||
| 54 | public int function, fill_style; | 50 | public int function, fill_style; |
| 55 | public int foreground, background; | 51 | public int foreground, background; |
| 56 | public int clip_x_origin, clip_y_origin; | 52 | public int clip_x_origin, clip_y_origin; |
| @@ -72,12 +68,6 @@ public final class EmacsGC extends EmacsHandleObject | |||
| 72 | rectangles changed. 0 if there are no clip rectangles. */ | 68 | rectangles changed. 0 if there are no clip rectangles. */ |
| 73 | public long clipRectID; | 69 | public long clipRectID; |
| 74 | 70 | ||
| 75 | static | ||
| 76 | { | ||
| 77 | xorAlu = new PorterDuffXfermode (Mode.XOR); | ||
| 78 | srcInAlu = new PorterDuffXfermode (Mode.SRC_IN); | ||
| 79 | } | ||
| 80 | |||
| 81 | /* The following fields are only set on immutable GCs. */ | 71 | /* The following fields are only set on immutable GCs. */ |
| 82 | 72 | ||
| 83 | public | 73 | public |
| @@ -131,8 +121,6 @@ public final class EmacsGC extends EmacsHandleObject | |||
| 131 | /* A line_width of 0 is equivalent to that of 1. */ | 121 | /* A line_width of 0 is equivalent to that of 1. */ |
| 132 | gcPaint.setStrokeWidth (line_width < 1 ? 1 : line_width); | 122 | gcPaint.setStrokeWidth (line_width < 1 ? 1 : line_width); |
| 133 | gcPaint.setColor (foreground | 0xff000000); | 123 | gcPaint.setColor (foreground | 0xff000000); |
| 134 | gcPaint.setXfermode (function == GC_XOR | ||
| 135 | ? xorAlu : srcInAlu); | ||
| 136 | 124 | ||
| 137 | /* Update the stipple object with the new stipple bitmap, or delete | 125 | /* Update the stipple object with the new stipple bitmap, or delete |
| 138 | it if the stipple has been cleared on systems too old to support | 126 | it if the stipple has been cleared on systems too old to support |
diff --git a/java/org/gnu/emacs/EmacsSafThread.java b/java/org/gnu/emacs/EmacsSafThread.java index 14c3f222833..ee8c2e7e0c3 100644 --- a/java/org/gnu/emacs/EmacsSafThread.java +++ b/java/org/gnu/emacs/EmacsSafThread.java | |||
| @@ -1623,10 +1623,10 @@ public final class EmacsSafThread extends HandlerThread | |||
| 1623 | mode is merely w. | 1623 | mode is merely w. |
| 1624 | 1624 | ||
| 1625 | This may be ascribed to a mix-up in Android's documentation | 1625 | This may be ascribed to a mix-up in Android's documentation |
| 1626 | regardin DocumentsProvider: the `openDocument' function is only | 1626 | regarding DocumentsProvider: the `openDocument' function is only |
| 1627 | documented to accept r or rw, whereas the default | 1627 | documented to accept r or rw, whereas the default implementation |
| 1628 | implementation of the `openFile' function (which documents rwt) | 1628 | of the `openFile' function (which documents rwt) delegates to |
| 1629 | delegates to `openDocument'. */ | 1629 | `openDocument'. */ |
| 1630 | 1630 | ||
| 1631 | if (read && write && truncate && fileDescriptor != null | 1631 | if (read && write && truncate && fileDescriptor != null |
| 1632 | && !EmacsNative.ftruncate (fileDescriptor.getFd ())) | 1632 | && !EmacsNative.ftruncate (fileDescriptor.getFd ())) |
diff --git a/src/android.c b/src/android.c index 2777add5059..c76afdb9bf2 100644 --- a/src/android.c +++ b/src/android.c | |||
| @@ -4381,286 +4381,6 @@ android_blit_copy (int src_x, int src_y, int width, int height, | |||
| 4381 | } | 4381 | } |
| 4382 | 4382 | ||
| 4383 | 4383 | ||
| 4384 | /* Xor a rectangle SRC_X, SRC_Y, WIDTH and HEIGHT from SRC, described | ||
| 4385 | by SRC_INFO, to DST_X and DST_Y in DST, as described by DST_INFO. | ||
| 4386 | |||
| 4387 | Ignore the alpha channel when computing the exclusive-or of the | ||
| 4388 | destination pixel. | ||
| 4389 | |||
| 4390 | If MASK is set, mask the source data using MASK_INFO, translating | ||
| 4391 | it by GC->clip_x_origin and GC->clip_y_origin. MASK must be a | ||
| 4392 | pixmap of depth 1. | ||
| 4393 | |||
| 4394 | N.B. that currently only copies between bitmaps of depth 24 are | ||
| 4395 | implemented. */ | ||
| 4396 | |||
| 4397 | static void | ||
| 4398 | android_blit_xor (int src_x, int src_y, int width, int height, | ||
| 4399 | int dst_x, int dst_y, struct android_gc *gc, | ||
| 4400 | unsigned char *src, AndroidBitmapInfo *src_info, | ||
| 4401 | unsigned char *dst, AndroidBitmapInfo *dst_info, | ||
| 4402 | unsigned char *mask, AndroidBitmapInfo *mask_info) | ||
| 4403 | { | ||
| 4404 | #if 0 | ||
| 4405 | uintptr_t start, end; | ||
| 4406 | int mask_offset; | ||
| 4407 | size_t pixel, offset, offset1; | ||
| 4408 | unsigned char *src_current, *dst_current; | ||
| 4409 | unsigned char *mask_current; | ||
| 4410 | int overflow, temp, i; | ||
| 4411 | bool backwards; | ||
| 4412 | unsigned int *long_src, *long_dst; | ||
| 4413 | #endif /* 0 */ | ||
| 4414 | |||
| 4415 | /* Note that this alu hasn't been tested -- it probably does not | ||
| 4416 | work! */ | ||
| 4417 | emacs_abort (); | ||
| 4418 | |||
| 4419 | #if 0 | ||
| 4420 | /* Assert that the specified coordinates are within bounds. */ | ||
| 4421 | eassert (src_x >= 0 && src_y >= 0 | ||
| 4422 | && dst_x >= 0 && dst_y >= 0); | ||
| 4423 | eassert (src_x + width <= src_info->width); | ||
| 4424 | eassert (src_y + height <= src_info->height); | ||
| 4425 | eassert (dst_x + width <= dst_info->width); | ||
| 4426 | eassert (dst_y + height <= dst_info->height); | ||
| 4427 | |||
| 4428 | /* Now check that each bitmap has the correct format. */ | ||
| 4429 | eassert (src_info->format == dst_info->format | ||
| 4430 | && src_info->format == ANDROID_BITMAP_FORMAT_RGBA_8888); | ||
| 4431 | pixel = sizeof (unsigned int); | ||
| 4432 | |||
| 4433 | /* Android doesn't have A1 bitmaps, so A8 is used to represent | ||
| 4434 | packed bitmaps of depth 1. */ | ||
| 4435 | eassert (!mask || mask_info->format == ANDROID_BITMAP_FORMAT_A_8); | ||
| 4436 | |||
| 4437 | /* Calculate the address of the first pixel of the first row to be | ||
| 4438 | copied in both src and dst. Compare them to determine the | ||
| 4439 | direction in which the copy is to take place. */ | ||
| 4440 | |||
| 4441 | overflow = ckd_mul (&start, src_y, src_info->stride); | ||
| 4442 | overflow |= ckd_mul (&end, src_x, pixel); | ||
| 4443 | overflow |= ckd_add (&start, (uintptr_t) src, start); | ||
| 4444 | |||
| 4445 | if (overflow) | ||
| 4446 | return; | ||
| 4447 | |||
| 4448 | src_current = (unsigned char *) start; | ||
| 4449 | |||
| 4450 | overflow = ckd_mul (&start, dst_y, src_info->stride); | ||
| 4451 | overflow |= ckd_mul (&end, dst_x, pixel); | ||
| 4452 | overflow |= ckd_add (&start, (uintptr_t) dst, start); | ||
| 4453 | |||
| 4454 | if (overflow) | ||
| 4455 | return; | ||
| 4456 | |||
| 4457 | dst_current = (unsigned char *) start; | ||
| 4458 | backwards = false; | ||
| 4459 | |||
| 4460 | /* Now see if copying should proceed from the bottom up. */ | ||
| 4461 | |||
| 4462 | if (src == dst && dst_current >= src_current) | ||
| 4463 | { | ||
| 4464 | backwards = true; | ||
| 4465 | |||
| 4466 | /* Walk src and dst from bottom to top, in order to avoid | ||
| 4467 | overlap. Calculate the coordinate of the last pixel of the | ||
| 4468 | last row in both src and dst. */ | ||
| 4469 | |||
| 4470 | overflow = ckd_mul (&start, src_y + height - 1, | ||
| 4471 | src_info->stride); | ||
| 4472 | if (mask) /* If a mask is set, put the pointers before the end | ||
| 4473 | of the row. */ | ||
| 4474 | overflow |= ckd_mul (&end, src_x + width - 1, pixel); | ||
| 4475 | else | ||
| 4476 | overflow |= ckd_mul (&end, src_x, pixel); | ||
| 4477 | overflow |= ckd_add (&start, start, end); | ||
| 4478 | overflow |= ckd_add (&start, (uintptr_t) src, start); | ||
| 4479 | |||
| 4480 | if (overflow) | ||
| 4481 | return; | ||
| 4482 | |||
| 4483 | src_current = (unsigned char *) start; | ||
| 4484 | |||
| 4485 | overflow = ckd_mul (&start, dst_y + height - 1, | ||
| 4486 | dst_info->stride); | ||
| 4487 | if (mask) /* If a mask is set, put the pointers before the end | ||
| 4488 | of the row. */ | ||
| 4489 | overflow |= ckd_mul (&end, dst_x + width - 1, pixel); | ||
| 4490 | else | ||
| 4491 | overflow |= ckd_mul (&end, dst_x, pixel); | ||
| 4492 | overflow |= ckd_add (&start, start, end); | ||
| 4493 | overflow |= ckd_add (&start, (uintptr_t) dst, start); | ||
| 4494 | |||
| 4495 | if (overflow) | ||
| 4496 | return; | ||
| 4497 | |||
| 4498 | dst_current = (unsigned char *) start; | ||
| 4499 | } | ||
| 4500 | |||
| 4501 | if (!mask) | ||
| 4502 | { | ||
| 4503 | /* Change the direction of the copy depending on how SRC and DST | ||
| 4504 | overlap. */ | ||
| 4505 | |||
| 4506 | for (i = 0; i < height; ++i) | ||
| 4507 | { | ||
| 4508 | if (backwards) | ||
| 4509 | { | ||
| 4510 | for (i = width - 1; i <= 0; --i) | ||
| 4511 | (((unsigned int *) dst_current)[i]) | ||
| 4512 | /* Keep the alpha channel intact. */ | ||
| 4513 | ^= (((unsigned int *) src_current)[i]) & 0xffffff; | ||
| 4514 | |||
| 4515 | /* Proceed to the last row. */ | ||
| 4516 | src_current -= src_info->stride; | ||
| 4517 | dst_current -= dst_info->stride; | ||
| 4518 | } | ||
| 4519 | else | ||
| 4520 | { | ||
| 4521 | for (i = 0; i < width; ++i) | ||
| 4522 | (((unsigned int *) dst_current)[i]) | ||
| 4523 | /* Keep the alpha channel intact. */ | ||
| 4524 | ^= (((unsigned int *) src_current)[i]) & 0xffffff; | ||
| 4525 | |||
| 4526 | /* Proceed to the next row. */ | ||
| 4527 | src_current += src_info->stride; | ||
| 4528 | dst_current += dst_info->stride; | ||
| 4529 | } | ||
| 4530 | } | ||
| 4531 | } | ||
| 4532 | else | ||
| 4533 | { | ||
| 4534 | /* Adjust the source and destination Y. The start is MAX | ||
| 4535 | (dst_y, gc->clip_y_origin); the difference between that value | ||
| 4536 | and dst_y is the offset to apply to src_y. */ | ||
| 4537 | |||
| 4538 | temp = dst_y; | ||
| 4539 | dst_y = MAX (dst_y, gc->clip_y_origin); | ||
| 4540 | src_y += dst_y - temp; | ||
| 4541 | height -= dst_y - temp; | ||
| 4542 | |||
| 4543 | /* Verify that the bounds are correct. */ | ||
| 4544 | eassert (dst_y + height | ||
| 4545 | <= gc->clip_y_origin + mask_info->height); | ||
| 4546 | eassert (dst_y >= gc->clip_y_origin); | ||
| 4547 | |||
| 4548 | /* There is a mask. For each scan line... */ | ||
| 4549 | |||
| 4550 | if (backwards) | ||
| 4551 | { | ||
| 4552 | /* Calculate the number of pixels at the end of the | ||
| 4553 | mask. */ | ||
| 4554 | |||
| 4555 | mask_offset = dst_x + width; | ||
| 4556 | mask_offset -= mask_info->width + gc->clip_x_origin; | ||
| 4557 | |||
| 4558 | if (mask_info < 0) | ||
| 4559 | mask_info = 0; | ||
| 4560 | |||
| 4561 | /* Calculate the last column of the mask that will be | ||
| 4562 | consulted. */ | ||
| 4563 | |||
| 4564 | temp = dst_x - gc->clip_x_origin; | ||
| 4565 | temp += MIN (mask_info->width - temp, | ||
| 4566 | width - mask_offset); | ||
| 4567 | |||
| 4568 | if (temp < 0) | ||
| 4569 | return; | ||
| 4570 | |||
| 4571 | /* Now calculate the last row of the mask that will be | ||
| 4572 | consulted. */ | ||
| 4573 | i = dst_y - gc->clip_y_origin + height; | ||
| 4574 | |||
| 4575 | /* Turn both into offsets. */ | ||
| 4576 | |||
| 4577 | if (ckd_mul (&offset, temp, pixel) | ||
| 4578 | || ckd_mul (&offset1, i, mask_info->stride) | ||
| 4579 | || ckd_add (&offset, offset, offset1) | ||
| 4580 | || ckd_add (&start, (uintptr_t) mask, offset)) | ||
| 4581 | return; | ||
| 4582 | |||
| 4583 | mask = mask_current = (unsigned char *) start; | ||
| 4584 | |||
| 4585 | for (i = 0; i < height; ++i) | ||
| 4586 | { | ||
| 4587 | /* Skip backwards past the end of the mask. */ | ||
| 4588 | |||
| 4589 | long_src = (unsigned int *) (src_current - mask_offset * pixel); | ||
| 4590 | long_dst = (unsigned int *) (dst_current - mask_offset * pixel); | ||
| 4591 | mask = mask_current; | ||
| 4592 | |||
| 4593 | /* For each pixel covered by the mask... */ | ||
| 4594 | temp = MIN (mask_info->width - temp, width - mask_offset); | ||
| 4595 | while (temp--) | ||
| 4596 | /* XOR the source to the destination, masked by the | ||
| 4597 | mask. */ | ||
| 4598 | *long_dst-- ^= ((*(long_src--) & (0u - (*(mask--) & 1))) | ||
| 4599 | & 0xffffff); | ||
| 4600 | |||
| 4601 | /* Return to the last row. */ | ||
| 4602 | src_current -= src_info->stride; | ||
| 4603 | dst_current -= dst_info->stride; | ||
| 4604 | mask_current -= mask_info->stride; | ||
| 4605 | } | ||
| 4606 | } | ||
| 4607 | else | ||
| 4608 | { | ||
| 4609 | /* Calculate the first column of the mask that will be | ||
| 4610 | consulted. */ | ||
| 4611 | |||
| 4612 | mask_offset = dst_x - gc->clip_x_origin; | ||
| 4613 | |||
| 4614 | /* Adjust the mask by that much. */ | ||
| 4615 | |||
| 4616 | if (mask_offset > 0) | ||
| 4617 | mask += mask_offset; | ||
| 4618 | else | ||
| 4619 | { | ||
| 4620 | /* Offset src and dst by the mask offset. */ | ||
| 4621 | src_current += -mask_offset * pixel; | ||
| 4622 | dst_current += -mask_offset * pixel; | ||
| 4623 | width -= mask_offset; | ||
| 4624 | } | ||
| 4625 | |||
| 4626 | /* Now move mask to the position of the first row. */ | ||
| 4627 | |||
| 4628 | mask += gc->clip_y_origin * mask_info->stride; | ||
| 4629 | |||
| 4630 | for (i = 0; i < height; ++i) | ||
| 4631 | { | ||
| 4632 | long_src = (unsigned int *) src_current; | ||
| 4633 | long_dst = (unsigned int *) dst_current; | ||
| 4634 | mask_current = mask; | ||
| 4635 | |||
| 4636 | if (mask_offset > 0) | ||
| 4637 | { | ||
| 4638 | /* Copy bytes according to the mask. */ | ||
| 4639 | temp = MIN (mask_info->width - mask_offset, width); | ||
| 4640 | while (temp--) | ||
| 4641 | *long_dst++ ^= ((*(long_src++) | ||
| 4642 | & (0u - (*(mask_current++) & 1))) | ||
| 4643 | & 0xffffff); | ||
| 4644 | } | ||
| 4645 | else | ||
| 4646 | { | ||
| 4647 | /* Copy bytes according to the mask. */ | ||
| 4648 | temp = MIN (mask_info->width, width); | ||
| 4649 | while (temp--) | ||
| 4650 | *long_dst++ = ((*(long_src++) | ||
| 4651 | & (0u - (*(mask_current++) & 1))) | ||
| 4652 | & 0xffffff); | ||
| 4653 | } | ||
| 4654 | |||
| 4655 | src_current += src_info->stride; | ||
| 4656 | dst_current += dst_info->stride; | ||
| 4657 | mask += mask_info->stride; | ||
| 4658 | } | ||
| 4659 | } | ||
| 4660 | } | ||
| 4661 | #endif /* 0 */ | ||
| 4662 | } | ||
| 4663 | |||
| 4664 | void | 4384 | void |
| 4665 | android_copy_area (android_drawable src, android_drawable dest, | 4385 | android_copy_area (android_drawable src, android_drawable dest, |
| 4666 | struct android_gc *gc, int src_x, int src_y, | 4386 | struct android_gc *gc, int src_x, int src_y, |
| @@ -4763,10 +4483,10 @@ android_copy_area (android_drawable src, android_drawable dest, | |||
| 4763 | do_blit = android_blit_copy; | 4483 | do_blit = android_blit_copy; |
| 4764 | break; | 4484 | break; |
| 4765 | 4485 | ||
| 4766 | case ANDROID_GC_XOR: | 4486 | /* case ANDROID_GC_INVERT: */ |
| 4767 | do_blit = android_blit_xor; | 4487 | /* do_blit = android_blit_invert; */ |
| 4768 | break; | 4488 | /* A GC with its operation set to ANDROID_GC_INVERT is never given |
| 4769 | 4489 | to CopyArea. */ | |
| 4770 | default: | 4490 | default: |
| 4771 | emacs_abort (); | 4491 | emacs_abort (); |
| 4772 | } | 4492 | } |
diff --git a/src/androidgui.h b/src/androidgui.h index 5e4f6ec3989..3b3e08ca024 100644 --- a/src/androidgui.h +++ b/src/androidgui.h | |||
| @@ -56,7 +56,7 @@ struct android_point | |||
| 56 | enum android_gc_function | 56 | enum android_gc_function |
| 57 | { | 57 | { |
| 58 | ANDROID_GC_COPY = 0, | 58 | ANDROID_GC_COPY = 0, |
| 59 | ANDROID_GC_XOR = 1, | 59 | ANDROID_GC_INVERT = 1, |
| 60 | }; | 60 | }; |
| 61 | 61 | ||
| 62 | enum android_gc_value_mask | 62 | enum android_gc_value_mask |
diff --git a/src/androidterm.c b/src/androidterm.c index f849f0d9919..2979e5c1401 100644 --- a/src/androidterm.c +++ b/src/androidterm.c | |||
| @@ -151,14 +151,8 @@ android_flash (struct frame *f) | |||
| 151 | fd_set fds; | 151 | fd_set fds; |
| 152 | 152 | ||
| 153 | block_input (); | 153 | block_input (); |
| 154 | 154 | values.function = ANDROID_GC_INVERT; | |
| 155 | values.function = ANDROID_GC_XOR; | 155 | gc = android_create_gc (ANDROID_GC_FUNCTION, &values); |
| 156 | values.foreground = (FRAME_FOREGROUND_PIXEL (f) | ||
| 157 | ^ FRAME_BACKGROUND_PIXEL (f)); | ||
| 158 | |||
| 159 | gc = android_create_gc ((ANDROID_GC_FUNCTION | ||
| 160 | | ANDROID_GC_FOREGROUND), | ||
| 161 | &values); | ||
| 162 | 156 | ||
| 163 | /* Get the height not including a menu bar widget. */ | 157 | /* Get the height not including a menu bar widget. */ |
| 164 | int height = FRAME_PIXEL_HEIGHT (f); | 158 | int height = FRAME_PIXEL_HEIGHT (f); |