1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-05 22:20:24 -08:00

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.
This commit is contained in:
Po Lu 2024-05-02 11:31:37 +08:00
parent d3e95fcae9
commit b84fa71f89
7 changed files with 62 additions and 374 deletions

View file

@ -22,13 +22,23 @@ package org.gnu.emacs;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Xfermode;
import android.util.Log;
public final class EmacsDrawRectangle
{
private static final Xfermode srcInAlu;
static
{
srcInAlu = new PorterDuffXfermode (Mode.SRC_IN);
};
public static void
perform (EmacsDrawable drawable, EmacsGC gc,
int x, int y, int width, int height)
@ -40,8 +50,10 @@ public final class EmacsDrawRectangle
Canvas canvas;
Bitmap clipBitmap;
/* TODO implement stippling. */
if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
/* TODO implement stippling for this request. */
if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED
/* And GC_INVERT also. */
|| gc.fill_style == EmacsGC.GC_INVERT)
return;
canvas = drawable.lockCanvas (gc);
@ -103,7 +115,7 @@ public final class EmacsDrawRectangle
/* Set the transfer mode to SRC_IN to preserve only the parts
of the source that overlap with the mask. */
maskPaint = new Paint ();
maskPaint.setXfermode (EmacsGC.srcInAlu);
maskPaint.setXfermode (srcInAlu);
maskPaint.setStyle (Paint.Style.STROKE);
/* Draw the source. */

View file

@ -21,6 +21,8 @@ package org.gnu.emacs;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.graphics.Rect;
@ -28,30 +30,42 @@ import android.util.Log;
public final class EmacsFillRectangle
{
/* Color filter that inverts colors from the source. */
private static final ColorFilter invertFilter;
static
{
invertFilter = new ColorMatrixColorFilter (new float[] {
-1f, 0f, 0f, 0f, 255f,
0f, -1f, 0f, 0f, 255f,
0f, 0f, -1f, 0f, 255f,
0f, 0f, 0f, 1f, 0f,
});
};
public static void
perform (EmacsDrawable drawable, EmacsGC gc,
int x, int y, int width, int height)
{
Paint maskPaint, paint;
Canvas maskCanvas;
Bitmap maskBitmap;
Paint paint;
Rect rect;
Rect maskRect, dstRect;
Canvas canvas;
Bitmap clipBitmap;
Bitmap invertBitmap;
canvas = drawable.lockCanvas (gc);
if (canvas == null)
/* Clip masks are not respected or implemented when specified with
this request. */
if (canvas == null || gc.clip_mask != null)
return;
rect = new Rect (x, y, x + width, y + height);
paint = gc.gcPaint;
paint.setStyle (Paint.Style.FILL);
if (gc.clip_mask == null)
if (gc.function != EmacsGC.GC_INVERT)
{
paint = gc.gcPaint;
paint.setStyle (Paint.Style.FILL);
if (gc.fill_style != EmacsGC.GC_FILL_OPAQUE_STIPPLED)
canvas.drawRect (rect, paint);
else
@ -59,57 +73,17 @@ public final class EmacsFillRectangle
}
else
{
/* Drawing with a clip mask involves calculating the
intersection of the clip mask with the dst rect, and
extrapolating the corresponding part of the src rect. */
paint = new Paint ();
clipBitmap = gc.clip_mask.bitmap;
dstRect = new Rect (x, y, x + width, y + height);
maskRect = new Rect (gc.clip_x_origin,
gc.clip_y_origin,
(gc.clip_x_origin
+ clipBitmap.getWidth ()),
(gc.clip_y_origin
+ clipBitmap.getHeight ()));
if (!maskRect.setIntersect (dstRect, maskRect))
/* There is no intersection between the clip mask and the
dest rect. */
return;
/* Finally, create a temporary bitmap that is the size of
maskRect. */
maskBitmap
= Bitmap.createBitmap (maskRect.width (), maskRect.height (),
Bitmap.Config.ARGB_8888);
/* Draw the mask onto the maskBitmap. */
maskCanvas = new Canvas (maskBitmap);
maskRect.offset (-gc.clip_x_origin,
-gc.clip_y_origin);
maskCanvas.drawBitmap (gc.clip_mask.bitmap,
maskRect, new Rect (0, 0,
maskRect.width (),
maskRect.height ()),
paint);
maskRect.offset (gc.clip_x_origin,
gc.clip_y_origin);
/* Set the transfer mode to SRC_IN to preserve only the parts
of the source that overlap with the mask. */
maskPaint = new Paint ();
maskPaint.setXfermode (EmacsGC.srcInAlu);
/* Draw the source. */
maskCanvas.drawRect (maskRect, maskPaint);
/* Finally, draw the mask bitmap to the destination. */
paint.setXfermode (null);
canvas.drawBitmap (maskBitmap, null, maskRect, paint);
/* Recycle this unused bitmap. */
maskBitmap.recycle ();
/* Simply invert the destination, which is only implemented for
this request. As Android doesn't permit copying a bitmap to
itself, a copy of the source must be procured beforehand. */
invertBitmap = Bitmap.createBitmap (drawable.getBitmap (),
x, y, width, height);
paint.setColorFilter (invertFilter);
canvas.drawBitmap (invertBitmap, null, rect, paint);
paint.setColorFilter (null);
invertBitmap.recycle ();
}
drawable.damageRect (rect);

View file

@ -27,9 +27,7 @@ import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader.TileMode;
import android.graphics.Xfermode;
import android.graphics.drawable.BitmapDrawable;
@ -40,8 +38,8 @@ import android.os.Build;
public final class EmacsGC extends EmacsHandleObject
{
public static final int GC_COPY = 0;
public static final int GC_XOR = 1;
public static final int GC_COPY = 0;
public static final int GC_INVERT = 1;
public static final int GC_FILL_SOLID = 0;
public static final int GC_FILL_OPAQUE_STIPPLED = 1;
@ -49,8 +47,6 @@ public final class EmacsGC extends EmacsHandleObject
public static final int GC_LINE_SOLID = 0;
public static final int GC_LINE_ON_OFF_DASH = 1;
public static final Xfermode xorAlu, srcInAlu;
public int function, fill_style;
public int foreground, background;
public int clip_x_origin, clip_y_origin;
@ -72,12 +68,6 @@ public final class EmacsGC extends EmacsHandleObject
rectangles changed. 0 if there are no clip rectangles. */
public long clipRectID;
static
{
xorAlu = new PorterDuffXfermode (Mode.XOR);
srcInAlu = new PorterDuffXfermode (Mode.SRC_IN);
}
/* The following fields are only set on immutable GCs. */
public
@ -131,8 +121,6 @@ public final class EmacsGC extends EmacsHandleObject
/* A line_width of 0 is equivalent to that of 1. */
gcPaint.setStrokeWidth (line_width < 1 ? 1 : line_width);
gcPaint.setColor (foreground | 0xff000000);
gcPaint.setXfermode (function == GC_XOR
? xorAlu : srcInAlu);
/* Update the stipple object with the new stipple bitmap, or delete
it if the stipple has been cleared on systems too old to support

View file

@ -1623,10 +1623,10 @@ public final class EmacsSafThread extends HandlerThread
mode is merely w.
This may be ascribed to a mix-up in Android's documentation
regardin DocumentsProvider: the `openDocument' function is only
documented to accept r or rw, whereas the default
implementation of the `openFile' function (which documents rwt)
delegates to `openDocument'. */
regarding DocumentsProvider: the `openDocument' function is only
documented to accept r or rw, whereas the default implementation
of the `openFile' function (which documents rwt) delegates to
`openDocument'. */
if (read && write && truncate && fileDescriptor != null
&& !EmacsNative.ftruncate (fileDescriptor.getFd ()))