mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-03 18:41:25 -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:
parent
d3e95fcae9
commit
b84fa71f89
7 changed files with 62 additions and 374 deletions
|
|
@ -22,13 +22,23 @@ package org.gnu.emacs;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.PorterDuff.Mode;
|
||||||
|
import android.graphics.PorterDuffXfermode;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
|
import android.graphics.Xfermode;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public final class EmacsDrawRectangle
|
public final class EmacsDrawRectangle
|
||||||
{
|
{
|
||||||
|
private static final Xfermode srcInAlu;
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
srcInAlu = new PorterDuffXfermode (Mode.SRC_IN);
|
||||||
|
};
|
||||||
|
|
||||||
public static void
|
public static void
|
||||||
perform (EmacsDrawable drawable, EmacsGC gc,
|
perform (EmacsDrawable drawable, EmacsGC gc,
|
||||||
int x, int y, int width, int height)
|
int x, int y, int width, int height)
|
||||||
|
|
@ -40,8 +50,10 @@ public final class EmacsDrawRectangle
|
||||||
Canvas canvas;
|
Canvas canvas;
|
||||||
Bitmap clipBitmap;
|
Bitmap clipBitmap;
|
||||||
|
|
||||||
/* TODO implement stippling. */
|
/* TODO implement stippling for this request. */
|
||||||
if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED
|
||||||
|
/* And GC_INVERT also. */
|
||||||
|
|| gc.fill_style == EmacsGC.GC_INVERT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
canvas = drawable.lockCanvas (gc);
|
canvas = drawable.lockCanvas (gc);
|
||||||
|
|
@ -103,7 +115,7 @@ public final class EmacsDrawRectangle
|
||||||
/* Set the transfer mode to SRC_IN to preserve only the parts
|
/* Set the transfer mode to SRC_IN to preserve only the parts
|
||||||
of the source that overlap with the mask. */
|
of the source that overlap with the mask. */
|
||||||
maskPaint = new Paint ();
|
maskPaint = new Paint ();
|
||||||
maskPaint.setXfermode (EmacsGC.srcInAlu);
|
maskPaint.setXfermode (srcInAlu);
|
||||||
maskPaint.setStyle (Paint.Style.STROKE);
|
maskPaint.setStyle (Paint.Style.STROKE);
|
||||||
|
|
||||||
/* Draw the source. */
|
/* Draw the source. */
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ package org.gnu.emacs;
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.ColorFilter;
|
||||||
|
import android.graphics.ColorMatrixColorFilter;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
|
||||||
|
|
@ -28,30 +30,42 @@ import android.util.Log;
|
||||||
|
|
||||||
public final class EmacsFillRectangle
|
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
|
public static void
|
||||||
perform (EmacsDrawable drawable, EmacsGC gc,
|
perform (EmacsDrawable drawable, EmacsGC gc,
|
||||||
int x, int y, int width, int height)
|
int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
Paint maskPaint, paint;
|
Paint paint;
|
||||||
Canvas maskCanvas;
|
|
||||||
Bitmap maskBitmap;
|
|
||||||
Rect rect;
|
Rect rect;
|
||||||
Rect maskRect, dstRect;
|
|
||||||
Canvas canvas;
|
Canvas canvas;
|
||||||
Bitmap clipBitmap;
|
Bitmap invertBitmap;
|
||||||
|
|
||||||
canvas = drawable.lockCanvas (gc);
|
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;
|
return;
|
||||||
|
|
||||||
rect = new Rect (x, y, x + width, y + height);
|
rect = new Rect (x, y, x + width, y + height);
|
||||||
|
|
||||||
|
if (gc.function != EmacsGC.GC_INVERT)
|
||||||
|
{
|
||||||
paint = gc.gcPaint;
|
paint = gc.gcPaint;
|
||||||
paint.setStyle (Paint.Style.FILL);
|
paint.setStyle (Paint.Style.FILL);
|
||||||
|
|
||||||
if (gc.clip_mask == null)
|
|
||||||
{
|
|
||||||
if (gc.fill_style != EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
if (gc.fill_style != EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
||||||
canvas.drawRect (rect, paint);
|
canvas.drawRect (rect, paint);
|
||||||
else
|
else
|
||||||
|
|
@ -59,57 +73,17 @@ public final class EmacsFillRectangle
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Drawing with a clip mask involves calculating the
|
paint = new Paint ();
|
||||||
intersection of the clip mask with the dst rect, and
|
|
||||||
extrapolating the corresponding part of the src rect. */
|
|
||||||
|
|
||||||
clipBitmap = gc.clip_mask.bitmap;
|
/* Simply invert the destination, which is only implemented for
|
||||||
dstRect = new Rect (x, y, x + width, y + height);
|
this request. As Android doesn't permit copying a bitmap to
|
||||||
maskRect = new Rect (gc.clip_x_origin,
|
itself, a copy of the source must be procured beforehand. */
|
||||||
gc.clip_y_origin,
|
invertBitmap = Bitmap.createBitmap (drawable.getBitmap (),
|
||||||
(gc.clip_x_origin
|
x, y, width, height);
|
||||||
+ clipBitmap.getWidth ()),
|
paint.setColorFilter (invertFilter);
|
||||||
(gc.clip_y_origin
|
canvas.drawBitmap (invertBitmap, null, rect, paint);
|
||||||
+ clipBitmap.getHeight ()));
|
paint.setColorFilter (null);
|
||||||
|
invertBitmap.recycle ();
|
||||||
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 ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
drawable.damageRect (rect);
|
drawable.damageRect (rect);
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,7 @@ import android.graphics.Canvas;
|
||||||
import android.graphics.ColorFilter;
|
import android.graphics.ColorFilter;
|
||||||
import android.graphics.PorterDuff.Mode;
|
import android.graphics.PorterDuff.Mode;
|
||||||
import android.graphics.PorterDuffColorFilter;
|
import android.graphics.PorterDuffColorFilter;
|
||||||
import android.graphics.PorterDuffXfermode;
|
|
||||||
import android.graphics.Shader.TileMode;
|
import android.graphics.Shader.TileMode;
|
||||||
import android.graphics.Xfermode;
|
|
||||||
|
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
|
|
||||||
|
|
@ -41,7 +39,7 @@ import android.os.Build;
|
||||||
public final class EmacsGC extends EmacsHandleObject
|
public final class EmacsGC extends EmacsHandleObject
|
||||||
{
|
{
|
||||||
public static final int GC_COPY = 0;
|
public static final int GC_COPY = 0;
|
||||||
public static final int GC_XOR = 1;
|
public static final int GC_INVERT = 1;
|
||||||
|
|
||||||
public static final int GC_FILL_SOLID = 0;
|
public static final int GC_FILL_SOLID = 0;
|
||||||
public static final int GC_FILL_OPAQUE_STIPPLED = 1;
|
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_SOLID = 0;
|
||||||
public static final int GC_LINE_ON_OFF_DASH = 1;
|
public static final int GC_LINE_ON_OFF_DASH = 1;
|
||||||
|
|
||||||
public static final Xfermode xorAlu, srcInAlu;
|
|
||||||
|
|
||||||
public int function, fill_style;
|
public int function, fill_style;
|
||||||
public int foreground, background;
|
public int foreground, background;
|
||||||
public int clip_x_origin, clip_y_origin;
|
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. */
|
rectangles changed. 0 if there are no clip rectangles. */
|
||||||
public long clipRectID;
|
public long clipRectID;
|
||||||
|
|
||||||
static
|
|
||||||
{
|
|
||||||
xorAlu = new PorterDuffXfermode (Mode.XOR);
|
|
||||||
srcInAlu = new PorterDuffXfermode (Mode.SRC_IN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The following fields are only set on immutable GCs. */
|
/* The following fields are only set on immutable GCs. */
|
||||||
|
|
||||||
public
|
public
|
||||||
|
|
@ -131,8 +121,6 @@ public final class EmacsGC extends EmacsHandleObject
|
||||||
/* A line_width of 0 is equivalent to that of 1. */
|
/* A line_width of 0 is equivalent to that of 1. */
|
||||||
gcPaint.setStrokeWidth (line_width < 1 ? 1 : line_width);
|
gcPaint.setStrokeWidth (line_width < 1 ? 1 : line_width);
|
||||||
gcPaint.setColor (foreground | 0xff000000);
|
gcPaint.setColor (foreground | 0xff000000);
|
||||||
gcPaint.setXfermode (function == GC_XOR
|
|
||||||
? xorAlu : srcInAlu);
|
|
||||||
|
|
||||||
/* Update the stipple object with the new stipple bitmap, or delete
|
/* Update the stipple object with the new stipple bitmap, or delete
|
||||||
it if the stipple has been cleared on systems too old to support
|
it if the stipple has been cleared on systems too old to support
|
||||||
|
|
|
||||||
|
|
@ -1623,10 +1623,10 @@ public final class EmacsSafThread extends HandlerThread
|
||||||
mode is merely w.
|
mode is merely w.
|
||||||
|
|
||||||
This may be ascribed to a mix-up in Android's documentation
|
This may be ascribed to a mix-up in Android's documentation
|
||||||
regardin DocumentsProvider: the `openDocument' function is only
|
regarding DocumentsProvider: the `openDocument' function is only
|
||||||
documented to accept r or rw, whereas the default
|
documented to accept r or rw, whereas the default implementation
|
||||||
implementation of the `openFile' function (which documents rwt)
|
of the `openFile' function (which documents rwt) delegates to
|
||||||
delegates to `openDocument'. */
|
`openDocument'. */
|
||||||
|
|
||||||
if (read && write && truncate && fileDescriptor != null
|
if (read && write && truncate && fileDescriptor != null
|
||||||
&& !EmacsNative.ftruncate (fileDescriptor.getFd ()))
|
&& !EmacsNative.ftruncate (fileDescriptor.getFd ()))
|
||||||
|
|
|
||||||
288
src/android.c
288
src/android.c
|
|
@ -4381,286 +4381,6 @@ android_blit_copy (int src_x, int src_y, int width, int height,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Xor a rectangle SRC_X, SRC_Y, WIDTH and HEIGHT from SRC, described
|
|
||||||
by SRC_INFO, to DST_X and DST_Y in DST, as described by DST_INFO.
|
|
||||||
|
|
||||||
Ignore the alpha channel when computing the exclusive-or of the
|
|
||||||
destination pixel.
|
|
||||||
|
|
||||||
If MASK is set, mask the source data using MASK_INFO, translating
|
|
||||||
it by GC->clip_x_origin and GC->clip_y_origin. MASK must be a
|
|
||||||
pixmap of depth 1.
|
|
||||||
|
|
||||||
N.B. that currently only copies between bitmaps of depth 24 are
|
|
||||||
implemented. */
|
|
||||||
|
|
||||||
static void
|
|
||||||
android_blit_xor (int src_x, int src_y, int width, int height,
|
|
||||||
int dst_x, int dst_y, struct android_gc *gc,
|
|
||||||
unsigned char *src, AndroidBitmapInfo *src_info,
|
|
||||||
unsigned char *dst, AndroidBitmapInfo *dst_info,
|
|
||||||
unsigned char *mask, AndroidBitmapInfo *mask_info)
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
uintptr_t start, end;
|
|
||||||
int mask_offset;
|
|
||||||
size_t pixel, offset, offset1;
|
|
||||||
unsigned char *src_current, *dst_current;
|
|
||||||
unsigned char *mask_current;
|
|
||||||
int overflow, temp, i;
|
|
||||||
bool backwards;
|
|
||||||
unsigned int *long_src, *long_dst;
|
|
||||||
#endif /* 0 */
|
|
||||||
|
|
||||||
/* Note that this alu hasn't been tested -- it probably does not
|
|
||||||
work! */
|
|
||||||
emacs_abort ();
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* Assert that the specified coordinates are within bounds. */
|
|
||||||
eassert (src_x >= 0 && src_y >= 0
|
|
||||||
&& dst_x >= 0 && dst_y >= 0);
|
|
||||||
eassert (src_x + width <= src_info->width);
|
|
||||||
eassert (src_y + height <= src_info->height);
|
|
||||||
eassert (dst_x + width <= dst_info->width);
|
|
||||||
eassert (dst_y + height <= dst_info->height);
|
|
||||||
|
|
||||||
/* Now check that each bitmap has the correct format. */
|
|
||||||
eassert (src_info->format == dst_info->format
|
|
||||||
&& src_info->format == ANDROID_BITMAP_FORMAT_RGBA_8888);
|
|
||||||
pixel = sizeof (unsigned int);
|
|
||||||
|
|
||||||
/* Android doesn't have A1 bitmaps, so A8 is used to represent
|
|
||||||
packed bitmaps of depth 1. */
|
|
||||||
eassert (!mask || mask_info->format == ANDROID_BITMAP_FORMAT_A_8);
|
|
||||||
|
|
||||||
/* Calculate the address of the first pixel of the first row to be
|
|
||||||
copied in both src and dst. Compare them to determine the
|
|
||||||
direction in which the copy is to take place. */
|
|
||||||
|
|
||||||
overflow = ckd_mul (&start, src_y, src_info->stride);
|
|
||||||
overflow |= ckd_mul (&end, src_x, pixel);
|
|
||||||
overflow |= ckd_add (&start, (uintptr_t) src, start);
|
|
||||||
|
|
||||||
if (overflow)
|
|
||||||
return;
|
|
||||||
|
|
||||||
src_current = (unsigned char *) start;
|
|
||||||
|
|
||||||
overflow = ckd_mul (&start, dst_y, src_info->stride);
|
|
||||||
overflow |= ckd_mul (&end, dst_x, pixel);
|
|
||||||
overflow |= ckd_add (&start, (uintptr_t) dst, start);
|
|
||||||
|
|
||||||
if (overflow)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dst_current = (unsigned char *) start;
|
|
||||||
backwards = false;
|
|
||||||
|
|
||||||
/* Now see if copying should proceed from the bottom up. */
|
|
||||||
|
|
||||||
if (src == dst && dst_current >= src_current)
|
|
||||||
{
|
|
||||||
backwards = true;
|
|
||||||
|
|
||||||
/* Walk src and dst from bottom to top, in order to avoid
|
|
||||||
overlap. Calculate the coordinate of the last pixel of the
|
|
||||||
last row in both src and dst. */
|
|
||||||
|
|
||||||
overflow = ckd_mul (&start, src_y + height - 1,
|
|
||||||
src_info->stride);
|
|
||||||
if (mask) /* If a mask is set, put the pointers before the end
|
|
||||||
of the row. */
|
|
||||||
overflow |= ckd_mul (&end, src_x + width - 1, pixel);
|
|
||||||
else
|
|
||||||
overflow |= ckd_mul (&end, src_x, pixel);
|
|
||||||
overflow |= ckd_add (&start, start, end);
|
|
||||||
overflow |= ckd_add (&start, (uintptr_t) src, start);
|
|
||||||
|
|
||||||
if (overflow)
|
|
||||||
return;
|
|
||||||
|
|
||||||
src_current = (unsigned char *) start;
|
|
||||||
|
|
||||||
overflow = ckd_mul (&start, dst_y + height - 1,
|
|
||||||
dst_info->stride);
|
|
||||||
if (mask) /* If a mask is set, put the pointers before the end
|
|
||||||
of the row. */
|
|
||||||
overflow |= ckd_mul (&end, dst_x + width - 1, pixel);
|
|
||||||
else
|
|
||||||
overflow |= ckd_mul (&end, dst_x, pixel);
|
|
||||||
overflow |= ckd_add (&start, start, end);
|
|
||||||
overflow |= ckd_add (&start, (uintptr_t) dst, start);
|
|
||||||
|
|
||||||
if (overflow)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dst_current = (unsigned char *) start;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mask)
|
|
||||||
{
|
|
||||||
/* Change the direction of the copy depending on how SRC and DST
|
|
||||||
overlap. */
|
|
||||||
|
|
||||||
for (i = 0; i < height; ++i)
|
|
||||||
{
|
|
||||||
if (backwards)
|
|
||||||
{
|
|
||||||
for (i = width - 1; i <= 0; --i)
|
|
||||||
(((unsigned int *) dst_current)[i])
|
|
||||||
/* Keep the alpha channel intact. */
|
|
||||||
^= (((unsigned int *) src_current)[i]) & 0xffffff;
|
|
||||||
|
|
||||||
/* Proceed to the last row. */
|
|
||||||
src_current -= src_info->stride;
|
|
||||||
dst_current -= dst_info->stride;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (i = 0; i < width; ++i)
|
|
||||||
(((unsigned int *) dst_current)[i])
|
|
||||||
/* Keep the alpha channel intact. */
|
|
||||||
^= (((unsigned int *) src_current)[i]) & 0xffffff;
|
|
||||||
|
|
||||||
/* Proceed to the next row. */
|
|
||||||
src_current += src_info->stride;
|
|
||||||
dst_current += dst_info->stride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Adjust the source and destination Y. The start is MAX
|
|
||||||
(dst_y, gc->clip_y_origin); the difference between that value
|
|
||||||
and dst_y is the offset to apply to src_y. */
|
|
||||||
|
|
||||||
temp = dst_y;
|
|
||||||
dst_y = MAX (dst_y, gc->clip_y_origin);
|
|
||||||
src_y += dst_y - temp;
|
|
||||||
height -= dst_y - temp;
|
|
||||||
|
|
||||||
/* Verify that the bounds are correct. */
|
|
||||||
eassert (dst_y + height
|
|
||||||
<= gc->clip_y_origin + mask_info->height);
|
|
||||||
eassert (dst_y >= gc->clip_y_origin);
|
|
||||||
|
|
||||||
/* There is a mask. For each scan line... */
|
|
||||||
|
|
||||||
if (backwards)
|
|
||||||
{
|
|
||||||
/* Calculate the number of pixels at the end of the
|
|
||||||
mask. */
|
|
||||||
|
|
||||||
mask_offset = dst_x + width;
|
|
||||||
mask_offset -= mask_info->width + gc->clip_x_origin;
|
|
||||||
|
|
||||||
if (mask_info < 0)
|
|
||||||
mask_info = 0;
|
|
||||||
|
|
||||||
/* Calculate the last column of the mask that will be
|
|
||||||
consulted. */
|
|
||||||
|
|
||||||
temp = dst_x - gc->clip_x_origin;
|
|
||||||
temp += MIN (mask_info->width - temp,
|
|
||||||
width - mask_offset);
|
|
||||||
|
|
||||||
if (temp < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* Now calculate the last row of the mask that will be
|
|
||||||
consulted. */
|
|
||||||
i = dst_y - gc->clip_y_origin + height;
|
|
||||||
|
|
||||||
/* Turn both into offsets. */
|
|
||||||
|
|
||||||
if (ckd_mul (&offset, temp, pixel)
|
|
||||||
|| ckd_mul (&offset1, i, mask_info->stride)
|
|
||||||
|| ckd_add (&offset, offset, offset1)
|
|
||||||
|| ckd_add (&start, (uintptr_t) mask, offset))
|
|
||||||
return;
|
|
||||||
|
|
||||||
mask = mask_current = (unsigned char *) start;
|
|
||||||
|
|
||||||
for (i = 0; i < height; ++i)
|
|
||||||
{
|
|
||||||
/* Skip backwards past the end of the mask. */
|
|
||||||
|
|
||||||
long_src = (unsigned int *) (src_current - mask_offset * pixel);
|
|
||||||
long_dst = (unsigned int *) (dst_current - mask_offset * pixel);
|
|
||||||
mask = mask_current;
|
|
||||||
|
|
||||||
/* For each pixel covered by the mask... */
|
|
||||||
temp = MIN (mask_info->width - temp, width - mask_offset);
|
|
||||||
while (temp--)
|
|
||||||
/* XOR the source to the destination, masked by the
|
|
||||||
mask. */
|
|
||||||
*long_dst-- ^= ((*(long_src--) & (0u - (*(mask--) & 1)))
|
|
||||||
& 0xffffff);
|
|
||||||
|
|
||||||
/* Return to the last row. */
|
|
||||||
src_current -= src_info->stride;
|
|
||||||
dst_current -= dst_info->stride;
|
|
||||||
mask_current -= mask_info->stride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Calculate the first column of the mask that will be
|
|
||||||
consulted. */
|
|
||||||
|
|
||||||
mask_offset = dst_x - gc->clip_x_origin;
|
|
||||||
|
|
||||||
/* Adjust the mask by that much. */
|
|
||||||
|
|
||||||
if (mask_offset > 0)
|
|
||||||
mask += mask_offset;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Offset src and dst by the mask offset. */
|
|
||||||
src_current += -mask_offset * pixel;
|
|
||||||
dst_current += -mask_offset * pixel;
|
|
||||||
width -= mask_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now move mask to the position of the first row. */
|
|
||||||
|
|
||||||
mask += gc->clip_y_origin * mask_info->stride;
|
|
||||||
|
|
||||||
for (i = 0; i < height; ++i)
|
|
||||||
{
|
|
||||||
long_src = (unsigned int *) src_current;
|
|
||||||
long_dst = (unsigned int *) dst_current;
|
|
||||||
mask_current = mask;
|
|
||||||
|
|
||||||
if (mask_offset > 0)
|
|
||||||
{
|
|
||||||
/* Copy bytes according to the mask. */
|
|
||||||
temp = MIN (mask_info->width - mask_offset, width);
|
|
||||||
while (temp--)
|
|
||||||
*long_dst++ ^= ((*(long_src++)
|
|
||||||
& (0u - (*(mask_current++) & 1)))
|
|
||||||
& 0xffffff);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Copy bytes according to the mask. */
|
|
||||||
temp = MIN (mask_info->width, width);
|
|
||||||
while (temp--)
|
|
||||||
*long_dst++ = ((*(long_src++)
|
|
||||||
& (0u - (*(mask_current++) & 1)))
|
|
||||||
& 0xffffff);
|
|
||||||
}
|
|
||||||
|
|
||||||
src_current += src_info->stride;
|
|
||||||
dst_current += dst_info->stride;
|
|
||||||
mask += mask_info->stride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* 0 */
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
android_copy_area (android_drawable src, android_drawable dest,
|
android_copy_area (android_drawable src, android_drawable dest,
|
||||||
struct android_gc *gc, int src_x, int src_y,
|
struct android_gc *gc, int src_x, int src_y,
|
||||||
|
|
@ -4763,10 +4483,10 @@ android_copy_area (android_drawable src, android_drawable dest,
|
||||||
do_blit = android_blit_copy;
|
do_blit = android_blit_copy;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ANDROID_GC_XOR:
|
/* case ANDROID_GC_INVERT: */
|
||||||
do_blit = android_blit_xor;
|
/* do_blit = android_blit_invert; */
|
||||||
break;
|
/* A GC with its operation set to ANDROID_GC_INVERT is never given
|
||||||
|
to CopyArea. */
|
||||||
default:
|
default:
|
||||||
emacs_abort ();
|
emacs_abort ();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ struct android_point
|
||||||
enum android_gc_function
|
enum android_gc_function
|
||||||
{
|
{
|
||||||
ANDROID_GC_COPY = 0,
|
ANDROID_GC_COPY = 0,
|
||||||
ANDROID_GC_XOR = 1,
|
ANDROID_GC_INVERT = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum android_gc_value_mask
|
enum android_gc_value_mask
|
||||||
|
|
|
||||||
|
|
@ -151,14 +151,8 @@ android_flash (struct frame *f)
|
||||||
fd_set fds;
|
fd_set fds;
|
||||||
|
|
||||||
block_input ();
|
block_input ();
|
||||||
|
values.function = ANDROID_GC_INVERT;
|
||||||
values.function = ANDROID_GC_XOR;
|
gc = android_create_gc (ANDROID_GC_FUNCTION, &values);
|
||||||
values.foreground = (FRAME_FOREGROUND_PIXEL (f)
|
|
||||||
^ FRAME_BACKGROUND_PIXEL (f));
|
|
||||||
|
|
||||||
gc = android_create_gc ((ANDROID_GC_FUNCTION
|
|
||||||
| ANDROID_GC_FOREGROUND),
|
|
||||||
&values);
|
|
||||||
|
|
||||||
/* Get the height not including a menu bar widget. */
|
/* Get the height not including a menu bar widget. */
|
||||||
int height = FRAME_PIXEL_HEIGHT (f);
|
int height = FRAME_PIXEL_HEIGHT (f);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue