mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-12-01 08:17:38 +00:00
Update Java part of Android port
* java/org/gnu/emacs/EmacsCopyArea.java (EmacsCopyArea, perform) (paintTo): * java/org/gnu/emacs/EmacsDrawLine.java (EmacsDrawLine): * java/org/gnu/emacs/EmacsDrawPoint.java (EmacsDrawPoint): * java/org/gnu/emacs/EmacsDrawRectangle.java (EmacsDrawRectangle) (paintTo): * java/org/gnu/emacs/EmacsDrawable.java (EmacsDrawable): * java/org/gnu/emacs/EmacsFillPolygon.java (EmacsFillPolygon): * java/org/gnu/emacs/EmacsFillRectangle.java (EmacsFillRectangle): * java/org/gnu/emacs/EmacsFontDriver.java (EmacsFontDriver): * java/org/gnu/emacs/EmacsGC.java (EmacsGC): * java/org/gnu/emacs/EmacsNative.java (EmacsNative): * java/org/gnu/emacs/EmacsPixmap.java (EmacsPixmap): * java/org/gnu/emacs/EmacsSdk23FontDriver.java (EmacsSdk23FontDriver): * java/org/gnu/emacs/EmacsSdk7FontDriver.java (EmacsSdk7FontDriver, textExtents1, textExtents, draw): * java/org/gnu/emacs/EmacsService.java (EmacsService, copyArea): * java/org/gnu/emacs/EmacsSurfaceView.java (EmacsSurfaceView): * java/org/gnu/emacs/EmacsView.java (EmacsView, onLayout) (onFocusChanged): * java/org/gnu/emacs/EmacsWindow.java (EmacsWindow, run) (resizeWindow, lockCanvas, getBitmap, onKeyDown, onKeyUp) (onActivityDetached): Move rendering to main thread. Make drawing operations completely static.
This commit is contained in:
parent
e816e57039
commit
695e26079e
@ -27,54 +27,16 @@
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Xfermode;
|
||||
|
||||
public class EmacsCopyArea implements EmacsPaintReq
|
||||
public class EmacsCopyArea
|
||||
{
|
||||
private int src_x, src_y, dest_x, dest_y, width, height;
|
||||
private EmacsDrawable destination, source;
|
||||
private EmacsGC immutableGC;
|
||||
private static Xfermode xorAlu, srcInAlu, overAlu;
|
||||
private static Xfermode overAlu;
|
||||
|
||||
static
|
||||
{
|
||||
overAlu = new PorterDuffXfermode (Mode.SRC_OVER);
|
||||
xorAlu = new PorterDuffXfermode (Mode.XOR);
|
||||
srcInAlu = new PorterDuffXfermode (Mode.SRC_IN);
|
||||
};
|
||||
|
||||
public
|
||||
EmacsCopyArea (EmacsDrawable source, EmacsDrawable destination,
|
||||
int src_x, int src_y, int width, int height,
|
||||
int dest_x, int dest_y, EmacsGC immutableGC)
|
||||
{
|
||||
Bitmap bitmap;
|
||||
|
||||
this.destination = destination;
|
||||
this.source = source;
|
||||
this.src_x = src_x;
|
||||
this.src_y = src_y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.dest_x = dest_x;
|
||||
this.dest_y = dest_y;
|
||||
this.immutableGC = immutableGC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rect
|
||||
getRect ()
|
||||
{
|
||||
return new Rect (dest_x, dest_y, dest_x + width,
|
||||
dest_y + height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmacsDrawable
|
||||
getDrawable ()
|
||||
{
|
||||
return destination;
|
||||
}
|
||||
|
||||
private void
|
||||
private static void
|
||||
insetRectBy (Rect rect, int left, int top, int right,
|
||||
int bottom)
|
||||
{
|
||||
@ -84,30 +46,38 @@ public class EmacsCopyArea implements EmacsPaintReq
|
||||
rect.bottom -= bottom;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmacsGC
|
||||
getGC ()
|
||||
public static void
|
||||
perform (EmacsDrawable source, EmacsGC gc,
|
||||
EmacsDrawable destination,
|
||||
int src_x, int src_y, int width, int height,
|
||||
int dest_x, int dest_y)
|
||||
{
|
||||
return immutableGC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
paintTo (Canvas canvas, Paint paint, EmacsGC immutableGC)
|
||||
{
|
||||
int alu;
|
||||
int i;
|
||||
Bitmap bitmap;
|
||||
Paint maskPaint;
|
||||
Canvas maskCanvas;
|
||||
Paint maskPaint, paint;
|
||||
Canvas maskCanvas, canvas;
|
||||
Bitmap srcBitmap, maskBitmap, clipBitmap;
|
||||
Rect rect, maskRect, srcRect, dstRect, maskDestRect;
|
||||
boolean needFill;
|
||||
|
||||
/* TODO implement stippling. */
|
||||
if (immutableGC.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
||||
if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
||||
return;
|
||||
|
||||
alu = immutableGC.function;
|
||||
paint = gc.gcPaint;
|
||||
|
||||
canvas = destination.lockCanvas ();
|
||||
|
||||
if (canvas == null)
|
||||
return;
|
||||
|
||||
canvas.save ();
|
||||
|
||||
if (gc.real_clip_rects != null)
|
||||
{
|
||||
for (i = 0; i < gc.real_clip_rects.length; ++i)
|
||||
canvas.clipRect (gc.real_clip_rects[i]);
|
||||
}
|
||||
|
||||
/* A copy must be created or drawBitmap could end up overwriting
|
||||
itself. */
|
||||
@ -137,14 +107,10 @@ public class EmacsCopyArea implements EmacsPaintReq
|
||||
if (src_y + height > srcBitmap.getHeight ())
|
||||
height = srcBitmap.getHeight () - src_y;
|
||||
|
||||
rect = getRect ();
|
||||
rect = new Rect (dest_x, dest_y, dest_x + width,
|
||||
dest_y + height);
|
||||
|
||||
if (alu == EmacsGC.GC_COPY)
|
||||
paint.setXfermode (null);
|
||||
else
|
||||
paint.setXfermode (xorAlu);
|
||||
|
||||
if (immutableGC.clip_mask == null)
|
||||
if (gc.clip_mask == null)
|
||||
{
|
||||
bitmap = Bitmap.createBitmap (srcBitmap,
|
||||
src_x, src_y, width,
|
||||
@ -156,17 +122,17 @@ public class EmacsCopyArea implements EmacsPaintReq
|
||||
/* 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. */
|
||||
clipBitmap = immutableGC.clip_mask.bitmap;
|
||||
clipBitmap = gc.clip_mask.bitmap;
|
||||
dstRect = new Rect (dest_x, dest_y,
|
||||
dest_x + width,
|
||||
dest_y + height);
|
||||
maskRect = new Rect (immutableGC.clip_x_origin,
|
||||
immutableGC.clip_y_origin,
|
||||
(immutableGC.clip_x_origin
|
||||
maskRect = new Rect (gc.clip_x_origin,
|
||||
gc.clip_y_origin,
|
||||
(gc.clip_x_origin
|
||||
+ clipBitmap.getWidth ()),
|
||||
(immutableGC.clip_y_origin
|
||||
(gc.clip_y_origin
|
||||
+ clipBitmap.getHeight ()));
|
||||
clipBitmap = immutableGC.clip_mask.bitmap;
|
||||
clipBitmap = gc.clip_mask.bitmap;
|
||||
|
||||
if (!maskRect.setIntersect (dstRect, maskRect))
|
||||
/* There is no intersection between the clip mask and the
|
||||
@ -191,20 +157,21 @@ public class EmacsCopyArea implements EmacsPaintReq
|
||||
|
||||
/* Draw the mask onto the maskBitmap. */
|
||||
maskCanvas = new Canvas (maskBitmap);
|
||||
maskRect.offset (-immutableGC.clip_x_origin,
|
||||
-immutableGC.clip_y_origin);
|
||||
maskCanvas.drawBitmap (immutableGC.clip_mask.bitmap,
|
||||
maskRect, new Rect (0, 0,
|
||||
maskRect.width (),
|
||||
maskRect.height ()),
|
||||
paint);
|
||||
maskRect.offset (immutableGC.clip_x_origin,
|
||||
immutableGC.clip_y_origin);
|
||||
maskPaint = new Paint ();
|
||||
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 ()),
|
||||
maskPaint);
|
||||
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 (srcInAlu);
|
||||
maskPaint.setXfermode (EmacsGC.srcInAlu);
|
||||
|
||||
/* Draw the source. */
|
||||
maskDestRect = new Rect (0, 0, srcRect.width (),
|
||||
@ -215,6 +182,10 @@ maskRect, new Rect (0, 0,
|
||||
/* Finally, draw the mask bitmap to the destination. */
|
||||
paint.setXfermode (overAlu);
|
||||
canvas.drawBitmap (maskBitmap, null, maskRect, paint);
|
||||
gc.resetXfermode ();
|
||||
}
|
||||
|
||||
canvas.restore ();
|
||||
destination.damageRect (rect);
|
||||
}
|
||||
}
|
||||
|
@ -29,109 +29,49 @@
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Xfermode;
|
||||
|
||||
public class EmacsDrawLine implements EmacsPaintReq
|
||||
public class EmacsDrawLine
|
||||
{
|
||||
private int x, y, x2, y2;
|
||||
private EmacsDrawable drawable;
|
||||
private EmacsGC immutableGC;
|
||||
private static Xfermode xorAlu, srcInAlu;
|
||||
|
||||
static
|
||||
public static void
|
||||
perform (EmacsDrawable drawable, EmacsGC gc,
|
||||
int x, int y, int x2, int y2)
|
||||
{
|
||||
xorAlu = new PorterDuffXfermode (Mode.XOR);
|
||||
srcInAlu = new PorterDuffXfermode (Mode.SRC_IN);
|
||||
};
|
||||
Rect rect;
|
||||
Canvas canvas;
|
||||
Paint paint;
|
||||
int i;
|
||||
|
||||
public
|
||||
EmacsDrawLine (EmacsDrawable drawable, int x, int y,
|
||||
int x2, int y2, EmacsGC immutableGC)
|
||||
{
|
||||
this.drawable = drawable;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.x2 = x2;
|
||||
this.y2 = y2;
|
||||
this.immutableGC = immutableGC;
|
||||
}
|
||||
/* TODO implement stippling. */
|
||||
if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
||||
return;
|
||||
|
||||
@Override
|
||||
public Rect
|
||||
getRect ()
|
||||
{
|
||||
return new Rect (Math.min (x, x2 + 1),
|
||||
paint = gc.gcPaint;
|
||||
rect = new Rect (Math.min (x, x2 + 1),
|
||||
Math.min (y, y2 + 1),
|
||||
Math.max (x2 + 1, x),
|
||||
Math.max (y2 + 1, y));
|
||||
}
|
||||
canvas = drawable.lockCanvas ();
|
||||
|
||||
@Override
|
||||
public EmacsDrawable
|
||||
getDrawable ()
|
||||
{
|
||||
return drawable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmacsGC
|
||||
getGC ()
|
||||
{
|
||||
return immutableGC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
paintTo (Canvas canvas, Paint paint, EmacsGC immutableGC)
|
||||
{
|
||||
int alu;
|
||||
Paint maskPaint;
|
||||
Canvas maskCanvas;
|
||||
Bitmap maskBitmap;
|
||||
Rect rect, srcRect;
|
||||
int width, height;
|
||||
|
||||
/* TODO implement stippling. */
|
||||
if (immutableGC.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
||||
if (canvas == null)
|
||||
return;
|
||||
|
||||
alu = immutableGC.function;
|
||||
rect = getRect ();
|
||||
width = rect.width ();
|
||||
height = rect.height ();
|
||||
canvas.save ();
|
||||
|
||||
if (gc.real_clip_rects != null)
|
||||
{
|
||||
for (i = 0; i < gc.real_clip_rects.length; ++i)
|
||||
canvas.clipRect (gc.real_clip_rects[i]);
|
||||
}
|
||||
|
||||
paint.setStyle (Paint.Style.STROKE);
|
||||
|
||||
if (alu == EmacsGC.GC_COPY)
|
||||
paint.setXfermode (null);
|
||||
else
|
||||
paint.setXfermode (xorAlu);
|
||||
if (gc.clip_mask == null)
|
||||
canvas.drawLine ((float) x, (float) y,
|
||||
(float) x2, (float) y2,
|
||||
paint);
|
||||
|
||||
if (immutableGC.clip_mask == null)
|
||||
{
|
||||
paint.setColor (immutableGC.foreground | 0xff000000);
|
||||
canvas.drawLine ((float) x, (float) y,
|
||||
(float) x2, (float) y2,
|
||||
paint);
|
||||
}
|
||||
else
|
||||
{
|
||||
maskPaint = new Paint ();
|
||||
maskBitmap
|
||||
= immutableGC.clip_mask.bitmap.copy (Bitmap.Config.ARGB_8888,
|
||||
true);
|
||||
|
||||
if (maskBitmap == null)
|
||||
return;
|
||||
|
||||
maskPaint.setXfermode (srcInAlu);
|
||||
maskPaint.setColor (immutableGC.foreground | 0xff000000);
|
||||
maskCanvas = new Canvas (maskBitmap);
|
||||
srcRect = new Rect (0, 0, maskBitmap.getWidth (),
|
||||
maskBitmap.getHeight ());
|
||||
maskCanvas.drawLine (0.0f, 0.0f, (float) Math.abs (x - x2),
|
||||
(float) Math.abs (y - y2), maskPaint);
|
||||
canvas.drawBitmap (maskBitmap, srcRect, rect, paint);
|
||||
}
|
||||
|
||||
paint.setXfermode (null);
|
||||
/* DrawLine with clip mask not implemented; it is not used by
|
||||
Emacs. */
|
||||
canvas.restore ();
|
||||
drawable.damageRect (rect);
|
||||
}
|
||||
}
|
||||
|
@ -19,12 +19,13 @@
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
public class EmacsDrawPoint extends EmacsDrawRectangle
|
||||
public class EmacsDrawPoint
|
||||
{
|
||||
public
|
||||
EmacsDrawPoint (EmacsDrawable drawable, int x, int y,
|
||||
EmacsGC immutableGC)
|
||||
public static void
|
||||
perform (EmacsDrawable drawable,
|
||||
EmacsGC immutableGC, int x, int y)
|
||||
{
|
||||
super (drawable, x, y, 1, 1, immutableGC);
|
||||
EmacsDrawRectangle.perform (drawable, immutableGC,
|
||||
x, y, 1, 1);
|
||||
}
|
||||
}
|
||||
|
@ -22,110 +22,104 @@
|
||||
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.Xfermode;
|
||||
|
||||
public class EmacsDrawRectangle implements EmacsPaintReq
|
||||
import android.util.Log;
|
||||
|
||||
public class EmacsDrawRectangle
|
||||
{
|
||||
private int x, y, width, height;
|
||||
private EmacsDrawable drawable;
|
||||
private EmacsGC immutableGC;
|
||||
private static Xfermode xorAlu, srcInAlu;
|
||||
|
||||
static
|
||||
public static void
|
||||
perform (EmacsDrawable drawable, EmacsGC gc,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
xorAlu = new PorterDuffXfermode (Mode.XOR);
|
||||
srcInAlu = new PorterDuffXfermode (Mode.SRC_IN);
|
||||
};
|
||||
|
||||
public
|
||||
EmacsDrawRectangle (EmacsDrawable drawable, int x, int y,
|
||||
int width, int height,
|
||||
EmacsGC immutableGC)
|
||||
{
|
||||
this.drawable = drawable;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.immutableGC = immutableGC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rect
|
||||
getRect ()
|
||||
{
|
||||
/* Canvas.drawRect actually behaves exactly like PolyRectangle wrt
|
||||
to where the lines are placed, so extend the width and height
|
||||
by 1 in the damage rectangle. */
|
||||
return new Rect (x, y, x + width + 1, y + height + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmacsDrawable
|
||||
getDrawable ()
|
||||
{
|
||||
return drawable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmacsGC
|
||||
getGC ()
|
||||
{
|
||||
return immutableGC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
paintTo (Canvas canvas, Paint paint, EmacsGC immutableGC)
|
||||
{
|
||||
int alu;
|
||||
Paint maskPaint;
|
||||
int i;
|
||||
Paint maskPaint, paint;
|
||||
Canvas maskCanvas;
|
||||
Bitmap maskBitmap;
|
||||
Rect rect, srcRect;
|
||||
Rect rect;
|
||||
Rect maskRect, dstRect;
|
||||
Canvas canvas;
|
||||
Bitmap clipBitmap;
|
||||
|
||||
/* TODO implement stippling. */
|
||||
if (immutableGC.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
||||
if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
||||
return;
|
||||
|
||||
alu = immutableGC.function;
|
||||
canvas = drawable.lockCanvas ();
|
||||
|
||||
if (canvas == null)
|
||||
return;
|
||||
|
||||
canvas.save ();
|
||||
|
||||
if (gc.real_clip_rects != null)
|
||||
{
|
||||
for (i = 0; i < gc.real_clip_rects.length; ++i)
|
||||
canvas.clipRect (gc.real_clip_rects[i]);
|
||||
}
|
||||
|
||||
paint = gc.gcPaint;
|
||||
rect = new Rect (x, y, x + width, y + height);
|
||||
|
||||
paint.setStyle (Paint.Style.STROKE);
|
||||
paint.setStrokeWidth (1);
|
||||
|
||||
if (alu == EmacsGC.GC_COPY)
|
||||
paint.setXfermode (null);
|
||||
else
|
||||
paint.setXfermode (xorAlu);
|
||||
|
||||
if (immutableGC.clip_mask == null)
|
||||
{
|
||||
paint.setColor (immutableGC.foreground | 0xff000000);
|
||||
canvas.drawRect (rect, paint);
|
||||
}
|
||||
if (gc.clip_mask == null)
|
||||
canvas.drawRect (rect, paint);
|
||||
else
|
||||
{
|
||||
maskPaint = new Paint ();
|
||||
maskBitmap
|
||||
= immutableGC.clip_mask.bitmap.copy (Bitmap.Config.ARGB_8888,
|
||||
true);
|
||||
/* 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. */
|
||||
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 ()));
|
||||
clipBitmap = gc.clip_mask.bitmap;
|
||||
|
||||
if (maskBitmap == null)
|
||||
if (!maskRect.setIntersect (dstRect, maskRect))
|
||||
/* There is no intersection between the clip mask and the
|
||||
dest rect. */
|
||||
return;
|
||||
|
||||
maskPaint.setXfermode (srcInAlu);
|
||||
maskPaint.setColor (immutableGC.foreground | 0xff000000);
|
||||
/* 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);
|
||||
srcRect = new Rect (0, 0, maskBitmap.getWidth (),
|
||||
maskBitmap.getHeight ());
|
||||
maskCanvas.drawRect (srcRect, maskPaint);
|
||||
canvas.drawBitmap (maskBitmap, srcRect, rect, paint);
|
||||
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);
|
||||
maskPaint.setStyle (Paint.Style.STROKE);
|
||||
|
||||
/* Draw the source. */
|
||||
maskCanvas.drawRect (maskRect, maskPaint);
|
||||
|
||||
/* Finally, draw the mask bitmap to the destination. */
|
||||
paint.setXfermode (null);
|
||||
canvas.drawBitmap (maskBitmap, null, maskRect, paint);
|
||||
}
|
||||
|
||||
paint.setXfermode (null);
|
||||
canvas.restore ();
|
||||
drawable.damageRect (new Rect (x, y, x + width + 1,
|
||||
y + height + 1));
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,6 @@
|
||||
public interface EmacsDrawable
|
||||
{
|
||||
public Canvas lockCanvas ();
|
||||
public void unlockCanvas ();
|
||||
public void damageRect (Rect damageRect);
|
||||
public Bitmap getBitmap ();
|
||||
public boolean isDestroyed ();
|
||||
|
@ -26,34 +26,35 @@
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Xfermode;
|
||||
|
||||
public class EmacsFillPolygon implements EmacsPaintReq
|
||||
public class EmacsFillPolygon
|
||||
{
|
||||
private EmacsDrawable drawable;
|
||||
private EmacsGC immutableGC;
|
||||
private Path path;
|
||||
|
||||
private static Xfermode xorAlu, srcInAlu;
|
||||
|
||||
static
|
||||
{
|
||||
xorAlu = new PorterDuffXfermode (Mode.XOR);
|
||||
srcInAlu = new PorterDuffXfermode (Mode.SRC_IN);
|
||||
};
|
||||
|
||||
public
|
||||
EmacsFillPolygon (EmacsDrawable drawable, Point points[],
|
||||
EmacsGC immutableGC)
|
||||
public static void
|
||||
perform (EmacsDrawable drawable, EmacsGC gc, Point points[])
|
||||
{
|
||||
Canvas canvas;
|
||||
Path path;
|
||||
Paint paint;
|
||||
Rect rect;
|
||||
RectF rectF;
|
||||
int i;
|
||||
|
||||
this.drawable = drawable;
|
||||
this.immutableGC = immutableGC;
|
||||
canvas = drawable.lockCanvas ();
|
||||
|
||||
if (canvas == null)
|
||||
return;
|
||||
|
||||
paint = gc.gcPaint;
|
||||
|
||||
canvas.save ();
|
||||
|
||||
if (gc.real_clip_rects != null)
|
||||
{
|
||||
for (i = 0; i < gc.real_clip_rects.length; ++i)
|
||||
canvas.clipRect (gc.real_clip_rects[i]);
|
||||
}
|
||||
|
||||
/* Build the path from the given array of points. */
|
||||
path = new Path ();
|
||||
@ -67,84 +68,25 @@ public class EmacsFillPolygon implements EmacsPaintReq
|
||||
|
||||
path.close ();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rect
|
||||
getRect ()
|
||||
{
|
||||
RectF rect;
|
||||
/* Compute the damage rectangle. */
|
||||
rectF = new RectF (0, 0, 0, 0);
|
||||
path.computeBounds (rectF, true);
|
||||
|
||||
rect = new RectF (0, 0, 0, 0);
|
||||
path.computeBounds (rect, true);
|
||||
|
||||
return new Rect ((int) Math.floor (rect.left),
|
||||
(int) Math.floor (rect.top),
|
||||
(int) Math.ceil (rect.right),
|
||||
(int) Math.ceil (rect.bottom));
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmacsDrawable
|
||||
getDrawable ()
|
||||
{
|
||||
return drawable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmacsGC
|
||||
getGC ()
|
||||
{
|
||||
return immutableGC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
paintTo (Canvas canvas, Paint paint, EmacsGC immutableGC)
|
||||
{
|
||||
int alu;
|
||||
Paint maskPaint;
|
||||
Canvas maskCanvas;
|
||||
Bitmap maskBitmap;
|
||||
Rect rect;
|
||||
|
||||
/* TODO implement stippling. */
|
||||
if (immutableGC.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
||||
return;
|
||||
|
||||
alu = immutableGC.function;
|
||||
rect = getRect ();
|
||||
|
||||
if (alu == EmacsGC.GC_COPY)
|
||||
paint.setXfermode (null);
|
||||
else
|
||||
paint.setXfermode (xorAlu);
|
||||
rect = new Rect ((int) Math.floor (rectF.left),
|
||||
(int) Math.floor (rectF.top),
|
||||
(int) Math.ceil (rectF.right),
|
||||
(int) Math.ceil (rectF.bottom));
|
||||
|
||||
paint.setStyle (Paint.Style.FILL);
|
||||
|
||||
if (immutableGC.clip_mask == null)
|
||||
{
|
||||
paint.setColor (immutableGC.foreground | 0xff000000);
|
||||
canvas.drawPath (path, paint);
|
||||
}
|
||||
else
|
||||
{
|
||||
maskPaint = new Paint ();
|
||||
maskBitmap = immutableGC.clip_mask.bitmap;
|
||||
maskBitmap = maskBitmap.copy (Bitmap.Config.ARGB_8888,
|
||||
true);
|
||||
if (gc.clip_mask == null)
|
||||
canvas.drawPath (path, paint);
|
||||
|
||||
if (maskBitmap == null)
|
||||
return;
|
||||
canvas.restore ();
|
||||
drawable.damageRect (rect);
|
||||
|
||||
maskPaint.setXfermode (srcInAlu);
|
||||
maskPaint.setColor (immutableGC.foreground | 0xff000000);
|
||||
maskCanvas = new Canvas (maskBitmap);
|
||||
path.offset (-rect.left, -rect.top, null);
|
||||
maskCanvas.drawPath (path, maskPaint);
|
||||
canvas.drawBitmap (maskBitmap, new Rect (0, 0, rect.width (),
|
||||
rect.height ()),
|
||||
rect, paint);
|
||||
}
|
||||
/* FillPolygon with clip mask not implemented; it is not used by
|
||||
Emacs. */
|
||||
}
|
||||
}
|
||||
|
@ -22,108 +22,102 @@
|
||||
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.Xfermode;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class EmacsFillRectangle implements EmacsPaintReq
|
||||
public class EmacsFillRectangle
|
||||
{
|
||||
private int x, y, width, height;
|
||||
private EmacsDrawable drawable;
|
||||
private EmacsGC immutableGC;
|
||||
private static Xfermode xorAlu, srcInAlu;
|
||||
|
||||
static
|
||||
public static void
|
||||
perform (EmacsDrawable drawable, EmacsGC gc,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
xorAlu = new PorterDuffXfermode (Mode.XOR);
|
||||
srcInAlu = new PorterDuffXfermode (Mode.SRC_IN);
|
||||
};
|
||||
|
||||
public
|
||||
EmacsFillRectangle (EmacsDrawable drawable, int x, int y,
|
||||
int width, int height,
|
||||
EmacsGC immutableGC)
|
||||
{
|
||||
this.drawable = drawable;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.immutableGC = immutableGC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rect
|
||||
getRect ()
|
||||
{
|
||||
return new Rect (x, y, x + width, y + height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmacsDrawable
|
||||
getDrawable ()
|
||||
{
|
||||
return drawable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmacsGC
|
||||
getGC ()
|
||||
{
|
||||
return immutableGC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
paintTo (Canvas canvas, Paint paint, EmacsGC immutableGC)
|
||||
{
|
||||
int alu;
|
||||
Paint maskPaint;
|
||||
int i;
|
||||
Paint maskPaint, paint;
|
||||
Canvas maskCanvas;
|
||||
Bitmap maskBitmap;
|
||||
Rect rect, srcRect;
|
||||
Rect rect;
|
||||
Rect maskRect, dstRect;
|
||||
Canvas canvas;
|
||||
Bitmap clipBitmap;
|
||||
|
||||
/* TODO implement stippling. */
|
||||
if (immutableGC.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
||||
if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
||||
return;
|
||||
|
||||
alu = immutableGC.function;
|
||||
rect = getRect ();
|
||||
canvas = drawable.lockCanvas ();
|
||||
|
||||
if (canvas == null)
|
||||
return;
|
||||
|
||||
canvas.save ();
|
||||
|
||||
if (gc.real_clip_rects != null)
|
||||
{
|
||||
for (i = 0; i < gc.real_clip_rects.length; ++i)
|
||||
canvas.clipRect (gc.real_clip_rects[i]);
|
||||
}
|
||||
|
||||
paint = gc.gcPaint;
|
||||
rect = new Rect (x, y, x + width, y + height);
|
||||
|
||||
paint.setStyle (Paint.Style.FILL);
|
||||
|
||||
if (alu == EmacsGC.GC_COPY)
|
||||
paint.setXfermode (null);
|
||||
else
|
||||
paint.setXfermode (xorAlu);
|
||||
|
||||
if (immutableGC.clip_mask == null)
|
||||
{
|
||||
paint.setColor (immutableGC.foreground | 0xff000000);
|
||||
canvas.drawRect (rect, paint);
|
||||
}
|
||||
if (gc.clip_mask == null)
|
||||
canvas.drawRect (rect, paint);
|
||||
else
|
||||
{
|
||||
maskPaint = new Paint ();
|
||||
maskBitmap
|
||||
= immutableGC.clip_mask.bitmap.copy (Bitmap.Config.ARGB_8888,
|
||||
true);
|
||||
/* 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. */
|
||||
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 ()));
|
||||
clipBitmap = gc.clip_mask.bitmap;
|
||||
|
||||
if (maskBitmap == null)
|
||||
if (!maskRect.setIntersect (dstRect, maskRect))
|
||||
/* There is no intersection between the clip mask and the
|
||||
dest rect. */
|
||||
return;
|
||||
|
||||
maskPaint.setXfermode (srcInAlu);
|
||||
maskPaint.setColor (immutableGC.foreground | 0xff000000);
|
||||
/* 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);
|
||||
srcRect = new Rect (0, 0, maskBitmap.getWidth (),
|
||||
maskBitmap.getHeight ());
|
||||
maskCanvas.drawRect (srcRect, maskPaint);
|
||||
canvas.drawBitmap (maskBitmap, srcRect, rect, paint);
|
||||
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);
|
||||
}
|
||||
|
||||
paint.setXfermode (null);
|
||||
canvas.restore ();
|
||||
drawable.damageRect (rect);
|
||||
}
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ public abstract int draw (FontObject fontObject, EmacsGC gc,
|
||||
public static EmacsFontDriver
|
||||
createFontDriver ()
|
||||
{
|
||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
||||
return new EmacsSdk23FontDriver ();
|
||||
|
||||
return new EmacsSdk7FontDriver ();
|
||||
|
@ -20,6 +20,11 @@
|
||||
package org.gnu.emacs;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Paint;
|
||||
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.Xfermode;
|
||||
|
||||
/* X like graphics context structures. Keep the enums in synch with
|
||||
androidgui.h! */
|
||||
@ -32,14 +37,21 @@ public class EmacsGC extends EmacsHandleObject
|
||||
public static final int GC_FILL_SOLID = 0;
|
||||
public static final int GC_FILL_OPAQUE_STIPPLED = 1;
|
||||
|
||||
public static final Xfermode xorAlu, srcInAlu;
|
||||
|
||||
public int function, fill_style;
|
||||
public int foreground, background;
|
||||
public int clip_x_origin, clip_y_origin;
|
||||
public int ts_origin_x, ts_origin_y;
|
||||
public Rect clip_rects[];
|
||||
public Rect clip_rects[], real_clip_rects[];
|
||||
public EmacsPixmap clip_mask, stipple;
|
||||
private boolean dirty;
|
||||
private EmacsGC immutableGC;
|
||||
public Paint gcPaint;
|
||||
|
||||
static
|
||||
{
|
||||
xorAlu = new PorterDuffXfermode (Mode.XOR);
|
||||
srcInAlu = new PorterDuffXfermode (Mode.SRC_IN);
|
||||
}
|
||||
|
||||
/* The following fields are only set on immutable GCs. */
|
||||
|
||||
@ -55,62 +67,41 @@ public class EmacsGC extends EmacsHandleObject
|
||||
fill_style = GC_FILL_SOLID;
|
||||
function = GC_COPY;
|
||||
foreground = 0;
|
||||
background = 0xffffffff;
|
||||
background = 0xffffff;
|
||||
gcPaint = new Paint ();
|
||||
}
|
||||
|
||||
public
|
||||
EmacsGC (EmacsGC source)
|
||||
{
|
||||
super ((short) 0);
|
||||
|
||||
int i;
|
||||
|
||||
function = source.function;
|
||||
fill_style = source.fill_style;
|
||||
foreground = source.foreground;
|
||||
background = source.background;
|
||||
clip_x_origin = source.clip_x_origin;
|
||||
clip_y_origin = source.clip_y_origin;
|
||||
clip_rects = source.clip_rects;
|
||||
clip_mask = source.clip_mask;
|
||||
stipple = source.stipple;
|
||||
ts_origin_x = source.ts_origin_x;
|
||||
ts_origin_y = source.ts_origin_y;
|
||||
|
||||
/* Offset all the clip rects by ts_origin_x and ts_origin_y. */
|
||||
|
||||
if ((ts_origin_x != 0 || ts_origin_y != 0)
|
||||
&& clip_rects != null)
|
||||
{
|
||||
clip_rects = new Rect[clip_rects.length];
|
||||
|
||||
for (i = 0; i < clip_rects.length; ++i)
|
||||
{
|
||||
clip_rects[i] = new Rect (source.clip_rects[i]);
|
||||
clip_rects[i].offset (ts_origin_x,
|
||||
ts_origin_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Mark this GC as dirty. This means immutableGC will return a new
|
||||
copy of this GC the next time it is called. */
|
||||
/* Mark this GC as dirty. Apply parameters to the paint and
|
||||
recompute real_clip_rects. */
|
||||
|
||||
public void
|
||||
markDirty ()
|
||||
{
|
||||
dirty = true;
|
||||
int i;
|
||||
|
||||
if ((ts_origin_x != 0 || ts_origin_y != 0)
|
||||
&& clip_rects != null)
|
||||
{
|
||||
real_clip_rects = new Rect[clip_rects.length];
|
||||
|
||||
for (i = 0; i < clip_rects.length; ++i)
|
||||
{
|
||||
real_clip_rects[i] = new Rect (clip_rects[i]);
|
||||
real_clip_rects[i].offset (ts_origin_x, ts_origin_y);
|
||||
}
|
||||
}
|
||||
else
|
||||
real_clip_rects = clip_rects;
|
||||
|
||||
gcPaint.setColor (foreground | 0xff000000);
|
||||
gcPaint.setXfermode (function == GC_XOR
|
||||
? xorAlu : srcInAlu);
|
||||
}
|
||||
|
||||
public EmacsGC
|
||||
immutableGC ()
|
||||
public void
|
||||
resetXfermode ()
|
||||
{
|
||||
if (immutableGC == null || dirty)
|
||||
{
|
||||
immutableGC = new EmacsGC (this);
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
return immutableGC;
|
||||
};
|
||||
gcPaint.setXfermode (function == GC_XOR
|
||||
? xorAlu : srcInAlu);
|
||||
}
|
||||
};
|
||||
|
@ -79,6 +79,28 @@ public static native void sendKeyRelease (short window, long time, int state,
|
||||
/* Send an ANDROID_WINDOW_ACTION event. */
|
||||
public static native void sendWindowAction (short window, int action);
|
||||
|
||||
/* Send an ANDROID_ENTER_NOTIFY event. */
|
||||
public static native void sendEnterNotify (short window, int x, int y,
|
||||
long time);
|
||||
|
||||
/* Send an ANDROID_LEAVE_NOTIFY event. */
|
||||
public static native void sendLeaveNotify (short window, int x, int y,
|
||||
long time);
|
||||
|
||||
/* Send an ANDROID_MOTION_NOTIFY event. */
|
||||
public static native void sendMotionNotify (short window, int x, int y,
|
||||
long time);
|
||||
|
||||
/* Send an ANDROID_BUTTON_PRESS event. */
|
||||
public static native void sendButtonPress (short window, int x, int y,
|
||||
long time, int state,
|
||||
int button);
|
||||
|
||||
/* Send an ANDROID_BUTTON_RELEASE event. */
|
||||
public static native void sendButtonRelease (short window, int x, int y,
|
||||
long time, int state,
|
||||
int button);
|
||||
|
||||
static
|
||||
{
|
||||
System.loadLibrary ("emacs");
|
||||
|
@ -93,6 +93,8 @@ public class EmacsPixmap extends EmacsHandleObject
|
||||
break;
|
||||
}
|
||||
|
||||
bitmap.eraseColor (0xff000000);
|
||||
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.depth = depth;
|
||||
@ -108,13 +110,6 @@ public class EmacsPixmap extends EmacsHandleObject
|
||||
return canvas;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
unlockCanvas ()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
damageRect (Rect damageRect)
|
||||
|
@ -20,9 +20,80 @@
|
||||
package org.gnu.emacs;
|
||||
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
|
||||
public class EmacsSdk23FontDriver extends EmacsSdk7FontDriver
|
||||
{
|
||||
private void
|
||||
textExtents1 (Sdk7FontObject font, int code, FontMetrics metrics,
|
||||
Paint paint, Rect bounds)
|
||||
{
|
||||
char[] text;
|
||||
|
||||
text = new char[2];
|
||||
text[0] = (char) code;
|
||||
text[1] = 'c';
|
||||
|
||||
paint.getTextBounds (text, 0, 1, bounds);
|
||||
|
||||
metrics.lbearing = (short) bounds.left;
|
||||
metrics.rbearing = (short) bounds.right;
|
||||
metrics.ascent = (short) -bounds.top;
|
||||
metrics.descent = (short) bounds.bottom;
|
||||
metrics.width
|
||||
= (short) paint.getRunAdvance (text, 0, 1, 0, 1, false, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
textExtents (FontObject font, int code[], FontMetrics fontMetrics)
|
||||
{
|
||||
int i;
|
||||
Paint paintCache;
|
||||
Rect boundsCache;
|
||||
Sdk7FontObject fontObject;
|
||||
char[] text;
|
||||
float width;
|
||||
|
||||
fontObject = (Sdk7FontObject) font;
|
||||
paintCache = fontObject.typeface.typefacePaint;
|
||||
paintCache.setTextSize (fontObject.pixelSize);
|
||||
boundsCache = new Rect ();
|
||||
|
||||
if (code.length == 0)
|
||||
{
|
||||
fontMetrics.lbearing = 0;
|
||||
fontMetrics.rbearing = 0;
|
||||
fontMetrics.ascent = 0;
|
||||
fontMetrics.descent = 0;
|
||||
fontMetrics.width = 0;
|
||||
}
|
||||
else if (code.length == 1)
|
||||
textExtents1 ((Sdk7FontObject) font, code[0], fontMetrics,
|
||||
paintCache, boundsCache);
|
||||
else
|
||||
{
|
||||
text = new char[code.length + 1];
|
||||
|
||||
for (i = 0; i < code.length; ++i)
|
||||
text[i] = (char) code[i];
|
||||
|
||||
text[code.length] = 'c';
|
||||
|
||||
paintCache.getTextBounds (text, 0, code.length,
|
||||
boundsCache);
|
||||
width = paintCache.getRunAdvance (text, 0, code.length, 0,
|
||||
code.length,
|
||||
false, code.length);
|
||||
|
||||
fontMetrics.lbearing = (short) boundsCache.left;
|
||||
fontMetrics.rbearing = (short) boundsCache.right;
|
||||
fontMetrics.ascent = (short) -boundsCache.top;
|
||||
fontMetrics.descent = (short) boundsCache.bottom;
|
||||
fontMetrics.width = (short) width;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int
|
||||
hasChar (FontSpec font, char charCode)
|
||||
|
@ -243,93 +243,6 @@ protected class Sdk7FontObject extends FontObject
|
||||
}
|
||||
};
|
||||
|
||||
private class Sdk7DrawString implements EmacsPaintReq
|
||||
{
|
||||
private boolean drawBackground;
|
||||
private Sdk7FontObject fontObject;
|
||||
private char[] chars;
|
||||
private EmacsGC immutableGC;
|
||||
private EmacsDrawable drawable;
|
||||
private Rect rect;
|
||||
private int originX, originY;
|
||||
|
||||
public
|
||||
Sdk7DrawString (Sdk7FontObject fontObject, char[] chars,
|
||||
EmacsGC immutableGC, EmacsDrawable drawable,
|
||||
boolean drawBackground, Rect rect,
|
||||
int originX, int originY)
|
||||
{
|
||||
this.fontObject = fontObject;
|
||||
this.chars = chars;
|
||||
this.immutableGC = immutableGC;
|
||||
this.drawable = drawable;
|
||||
this.drawBackground = drawBackground;
|
||||
this.rect = rect;
|
||||
this.originX = originX;
|
||||
this.originY = originY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmacsDrawable
|
||||
getDrawable ()
|
||||
{
|
||||
return drawable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EmacsGC
|
||||
getGC ()
|
||||
{
|
||||
return immutableGC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
paintTo (Canvas canvas, Paint paint, EmacsGC immutableGC)
|
||||
{
|
||||
int scratch;
|
||||
|
||||
paint.setStyle (Paint.Style.FILL);
|
||||
|
||||
if (drawBackground)
|
||||
{
|
||||
paint.setColor (immutableGC.background | 0xff000000);
|
||||
canvas.drawRect (rect, paint);
|
||||
}
|
||||
|
||||
paint.setTextSize (fontObject.pixelSize);
|
||||
paint.setColor (immutableGC.foreground | 0xff000000);
|
||||
paint.setTypeface (fontObject.typeface.typeface);
|
||||
paint.setAntiAlias (true);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
|
||||
/* Disable hinting as that leads to displayed text not
|
||||
matching the computed metrics. */
|
||||
paint.setHinting (Paint.HINTING_OFF);
|
||||
|
||||
canvas.drawText (chars, 0, chars.length, originX, originY, paint);
|
||||
paint.setAntiAlias (false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rect
|
||||
getRect ()
|
||||
{
|
||||
Rect rect;
|
||||
|
||||
rect = new Rect ();
|
||||
|
||||
fontObject.typeface.typefacePaint.setTextSize (fontObject.pixelSize);
|
||||
fontObject.typeface.typefacePaint.getTextBounds (chars, 0, chars.length,
|
||||
rect);
|
||||
|
||||
/* Add the background rect to the damage as well. */
|
||||
rect.union (this.rect);
|
||||
|
||||
return rect;
|
||||
}
|
||||
};
|
||||
|
||||
private String[] fontFamilyList;
|
||||
private Sdk7Typeface[] typefaceList;
|
||||
private Sdk7Typeface fallbackTypeface;
|
||||
@ -498,14 +411,11 @@ private class Sdk7DrawString implements EmacsPaintReq
|
||||
Paint paint, Rect bounds)
|
||||
{
|
||||
char[] text;
|
||||
float[] width;
|
||||
|
||||
text = new char[1];
|
||||
text[0] = (char) code;
|
||||
|
||||
paint.getTextBounds (text, 0, 1, bounds);
|
||||
width = new float[1];
|
||||
paint.getTextWidths (text, 0, 1, width);
|
||||
|
||||
/* bounds is the bounding box of the glyph corresponding to CODE.
|
||||
Translate these into XCharStruct values.
|
||||
@ -526,7 +436,7 @@ raster. descent is the distance (once again counting
|
||||
metrics.rbearing = (short) bounds.right;
|
||||
metrics.ascent = (short) -bounds.top;
|
||||
metrics.descent = (short) bounds.bottom;
|
||||
metrics.width = (short) Math.round (width[0]);
|
||||
metrics.width = (short) paint.measureText ("" + text[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -563,7 +473,8 @@ else if (code.length == 1)
|
||||
for (i = 0; i < code.length; ++i)
|
||||
text[i] = (char) code[i];
|
||||
|
||||
paintCache.getTextBounds (text, 0, 1, boundsCache);
|
||||
paintCache.getTextBounds (text, 0, code.length,
|
||||
boundsCache);
|
||||
width = paintCache.measureText (text, 0, code.length);
|
||||
|
||||
fontMetrics.lbearing = (short) boundsCache.left;
|
||||
@ -587,11 +498,12 @@ else if (code.length == 1)
|
||||
int[] chars, int x, int y, int backgroundWidth,
|
||||
boolean withBackground)
|
||||
{
|
||||
Rect backgroundRect;
|
||||
Rect backgroundRect, bounds;
|
||||
Sdk7FontObject sdk7FontObject;
|
||||
Sdk7DrawString op;
|
||||
char[] charsArray;
|
||||
int i;
|
||||
Canvas canvas;
|
||||
Paint paint;
|
||||
|
||||
sdk7FontObject = (Sdk7FontObject) fontObject;
|
||||
charsArray = new char[chars.length];
|
||||
@ -605,12 +517,41 @@ else if (code.length == 1)
|
||||
backgroundRect.right = x + backgroundWidth;
|
||||
backgroundRect.bottom = y + sdk7FontObject.descent;
|
||||
|
||||
op = new Sdk7DrawString (sdk7FontObject, charsArray,
|
||||
gc.immutableGC (), drawable,
|
||||
withBackground,
|
||||
backgroundRect, x, y);
|
||||
canvas = drawable.lockCanvas ();
|
||||
|
||||
EmacsService.SERVICE.appendPaintOperation (op);
|
||||
if (canvas == null)
|
||||
return 0;
|
||||
|
||||
canvas.save ();
|
||||
paint = gc.gcPaint;
|
||||
|
||||
if (gc.real_clip_rects != null)
|
||||
{
|
||||
for (i = 0; i < gc.real_clip_rects.length; ++i)
|
||||
canvas.clipRect (gc.real_clip_rects[i]);
|
||||
}
|
||||
|
||||
paint.setStyle (Paint.Style.FILL);
|
||||
|
||||
if (withBackground)
|
||||
{
|
||||
paint.setColor (gc.background | 0xff000000);
|
||||
canvas.drawRect (backgroundRect, paint);
|
||||
paint.setColor (gc.foreground | 0xff000000);
|
||||
}
|
||||
|
||||
paint.setTextSize (sdk7FontObject.pixelSize);
|
||||
paint.setTypeface (sdk7FontObject.typeface.typeface);
|
||||
paint.setAntiAlias (true);
|
||||
canvas.drawText (charsArray, 0, chars.length, x, y, paint);
|
||||
|
||||
canvas.restore ();
|
||||
bounds = new Rect ();
|
||||
paint.getTextBounds (charsArray, 0, chars.length, bounds);
|
||||
bounds.offset (x, y);
|
||||
bounds.union (backgroundRect);
|
||||
drawable.damageRect (bounds);
|
||||
paint.setAntiAlias (false);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
@ -19,7 +19,6 @@
|
||||
|
||||
package org.gnu.emacs;
|
||||
|
||||
import java.lang.Runnable;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
@ -59,7 +58,6 @@ public class EmacsService extends Service
|
||||
|
||||
private EmacsThread thread;
|
||||
private Handler handler;
|
||||
private EmacsPaintQueue paintQueue;
|
||||
|
||||
/* Display metrics used by font backends. */
|
||||
public DisplayMetrics metrics;
|
||||
@ -191,126 +189,42 @@ else if (apiLevel >= Build.VERSION_CODES.DONUT)
|
||||
return view.thing;
|
||||
}
|
||||
|
||||
/* X drawing operations. These are quite primitive operations. The
|
||||
drawing queue is kept on the Emacs thread, but is periodically
|
||||
flushed to the application thread, upon buffers swaps and once it
|
||||
gets too big. */
|
||||
|
||||
|
||||
|
||||
private void
|
||||
ensurePaintQueue ()
|
||||
{
|
||||
if (paintQueue == null)
|
||||
paintQueue = new EmacsPaintQueue ();
|
||||
}
|
||||
|
||||
public void
|
||||
flushPaintQueue ()
|
||||
{
|
||||
final EmacsPaintQueue queue;
|
||||
|
||||
if (paintQueue == null)
|
||||
return;
|
||||
|
||||
if (paintQueue.numRequests < 1)
|
||||
/* No requests to flush. */
|
||||
return;
|
||||
|
||||
queue = paintQueue;
|
||||
|
||||
handler.post (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
queue.run ();
|
||||
}
|
||||
});
|
||||
|
||||
/* Clear the paint queue. */
|
||||
paintQueue = null;
|
||||
}
|
||||
|
||||
private void
|
||||
checkFlush ()
|
||||
{
|
||||
if (paintQueue != null
|
||||
&& paintQueue.numRequests > MAX_PENDING_REQUESTS)
|
||||
flushPaintQueue ();
|
||||
}
|
||||
|
||||
public void
|
||||
fillRectangle (EmacsDrawable drawable, EmacsGC gc,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
EmacsPaintReq req;
|
||||
|
||||
ensurePaintQueue ();
|
||||
|
||||
req = new EmacsFillRectangle (drawable, x, y,
|
||||
width, height,
|
||||
gc.immutableGC ());
|
||||
paintQueue.appendPaintOperation (req);
|
||||
checkFlush ();
|
||||
EmacsFillRectangle.perform (drawable, gc, x, y,
|
||||
width, height);
|
||||
}
|
||||
|
||||
public void
|
||||
fillPolygon (EmacsDrawable drawable, EmacsGC gc,
|
||||
Point points[])
|
||||
{
|
||||
EmacsPaintReq req;
|
||||
|
||||
ensurePaintQueue ();
|
||||
|
||||
req = new EmacsFillPolygon (drawable, points,
|
||||
gc.immutableGC ());
|
||||
paintQueue.appendPaintOperation (req);
|
||||
checkFlush ();
|
||||
EmacsFillPolygon.perform (drawable, gc, points);
|
||||
}
|
||||
|
||||
public void
|
||||
drawRectangle (EmacsDrawable drawable, EmacsGC gc,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
EmacsPaintReq req;
|
||||
|
||||
ensurePaintQueue ();
|
||||
|
||||
req = new EmacsDrawRectangle (drawable, x, y,
|
||||
width, height,
|
||||
gc.immutableGC ());
|
||||
paintQueue.appendPaintOperation (req);
|
||||
checkFlush ();
|
||||
EmacsDrawRectangle.perform (drawable, gc, x, y,
|
||||
width, height);
|
||||
}
|
||||
|
||||
public void
|
||||
drawLine (EmacsDrawable drawable, EmacsGC gc,
|
||||
int x, int y, int x2, int y2)
|
||||
{
|
||||
EmacsPaintReq req;
|
||||
|
||||
ensurePaintQueue ();
|
||||
|
||||
req = new EmacsDrawLine (drawable, x, y,
|
||||
x2, y2,
|
||||
gc.immutableGC ());
|
||||
paintQueue.appendPaintOperation (req);
|
||||
checkFlush ();
|
||||
EmacsDrawLine.perform (drawable, gc, x, y,
|
||||
x2, y2);
|
||||
}
|
||||
|
||||
public void
|
||||
drawPoint (EmacsDrawable drawable, EmacsGC gc,
|
||||
int x, int y)
|
||||
{
|
||||
EmacsPaintReq req;
|
||||
|
||||
ensurePaintQueue ();
|
||||
|
||||
req = new EmacsDrawPoint (drawable, x, y,
|
||||
gc.immutableGC ());
|
||||
paintQueue.appendPaintOperation (req);
|
||||
checkFlush ();
|
||||
EmacsDrawPoint.perform (drawable, gc, x, y);
|
||||
}
|
||||
|
||||
public void
|
||||
@ -319,15 +233,9 @@ else if (apiLevel >= Build.VERSION_CODES.DONUT)
|
||||
int srcX, int srcY, int width, int height, int destX,
|
||||
int destY)
|
||||
{
|
||||
EmacsPaintReq req;
|
||||
|
||||
ensurePaintQueue ();
|
||||
|
||||
req = new EmacsCopyArea (srcDrawable, dstDrawable,
|
||||
srcX, srcY, width, height, destX,
|
||||
destY, gc.immutableGC ());
|
||||
paintQueue.appendPaintOperation (req);
|
||||
checkFlush ();
|
||||
EmacsCopyArea.perform (srcDrawable, gc, dstDrawable,
|
||||
srcX, srcY, width, height, destX,
|
||||
destY);
|
||||
}
|
||||
|
||||
public void
|
||||
@ -342,12 +250,4 @@ else if (apiLevel >= Build.VERSION_CODES.DONUT)
|
||||
{
|
||||
window.clearArea (x, y, width, height);
|
||||
}
|
||||
|
||||
public void
|
||||
appendPaintOperation (EmacsPaintReq op)
|
||||
{
|
||||
ensurePaintQueue ();
|
||||
paintQueue.appendPaintOperation (op);
|
||||
checkFlush ();
|
||||
}
|
||||
};
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
public class EmacsSurfaceView extends SurfaceView
|
||||
{
|
||||
public Object surfaceChangeLock;
|
||||
private boolean created;
|
||||
|
||||
public
|
||||
@ -36,33 +37,36 @@ public class EmacsSurfaceView extends SurfaceView
|
||||
{
|
||||
super (view.getContext ());
|
||||
|
||||
surfaceChangeLock = new Object ();
|
||||
|
||||
getHolder ().addCallback (new SurfaceHolder.Callback () {
|
||||
@Override
|
||||
public void
|
||||
surfaceChanged (SurfaceHolder holder, int format,
|
||||
int width, int height)
|
||||
{
|
||||
/* Force a buffer swap now to get the contents of the Emacs
|
||||
view on screen. */
|
||||
view.swapBuffers (true);
|
||||
view.swapBuffers ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
surfaceCreated (SurfaceHolder holder)
|
||||
{
|
||||
created = true;
|
||||
|
||||
/* Force a buffer swap now to get the contents of the Emacs
|
||||
view on screen. */
|
||||
view.swapBuffers (true);
|
||||
synchronized (surfaceChangeLock)
|
||||
{
|
||||
created = true;
|
||||
view.swapBuffers ();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
surfaceDestroyed (SurfaceHolder holder)
|
||||
{
|
||||
created = false;
|
||||
synchronized (surfaceChangeLock)
|
||||
{
|
||||
created = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
import android.view.View;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
@ -64,6 +65,14 @@ public class EmacsView extends ViewGroup
|
||||
/* The associated surface view. */
|
||||
private EmacsSurfaceView surfaceView;
|
||||
|
||||
/* Whether or not a configure event must be sent for the next layout
|
||||
event regardless of what changed. */
|
||||
public boolean mustReportLayout;
|
||||
|
||||
/* If non-null, whether or not bitmaps must be recreated upon the
|
||||
next call to getBitmap. */
|
||||
private Rect bitmapDirty;
|
||||
|
||||
public
|
||||
EmacsView (EmacsWindow window)
|
||||
{
|
||||
@ -81,6 +90,43 @@ public class EmacsView extends ViewGroup
|
||||
addView (this.surfaceView);
|
||||
}
|
||||
|
||||
private void
|
||||
handleDirtyBitmap ()
|
||||
{
|
||||
/* Recreate the front and back buffer bitmaps. */
|
||||
bitmap
|
||||
= Bitmap.createBitmap (bitmapDirty.width (),
|
||||
bitmapDirty.height (),
|
||||
Bitmap.Config.ARGB_8888);
|
||||
bitmap.eraseColor (0xffffffff);
|
||||
|
||||
/* And canvases. */
|
||||
canvas = new Canvas (bitmap);
|
||||
|
||||
/* If Emacs is drawing to the bitmap right now from the
|
||||
main thread, the image contents are lost until the next
|
||||
ConfigureNotify and complete garbage. Sorry! */
|
||||
bitmapDirty = null;
|
||||
}
|
||||
|
||||
public synchronized Bitmap
|
||||
getBitmap ()
|
||||
{
|
||||
if (bitmapDirty != null)
|
||||
handleDirtyBitmap ();
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public synchronized Canvas
|
||||
getCanvas ()
|
||||
{
|
||||
if (bitmapDirty != null)
|
||||
handleDirtyBitmap ();
|
||||
|
||||
return canvas;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void
|
||||
onMeasure (int widthMeasureSpec, int heightMeasureSpec)
|
||||
@ -114,7 +160,7 @@ else if (MeasureSpec.getMode (heightMeasureSpec) == MeasureSpec.AT_MOST
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void
|
||||
protected synchronized void
|
||||
onLayout (boolean changed, int left, int top, int right,
|
||||
int bottom)
|
||||
{
|
||||
@ -122,19 +168,15 @@ else if (MeasureSpec.getMode (heightMeasureSpec) == MeasureSpec.AT_MOST
|
||||
View child;
|
||||
Rect windowRect;
|
||||
|
||||
if (changed)
|
||||
if (changed || mustReportLayout)
|
||||
{
|
||||
mustReportLayout = false;
|
||||
window.viewLayout (left, top, right, bottom);
|
||||
|
||||
/* Recreate the front and back buffer bitmaps. */
|
||||
bitmap
|
||||
= Bitmap.createBitmap (right - left, bottom - top,
|
||||
Bitmap.Config.ARGB_8888);
|
||||
|
||||
/* And canvases. */
|
||||
canvas = new Canvas (bitmap);
|
||||
}
|
||||
|
||||
if (changed)
|
||||
bitmapDirty = new Rect (left, top, right, bottom);
|
||||
|
||||
count = getChildCount ();
|
||||
|
||||
for (i = 0; i < count; ++i)
|
||||
@ -159,47 +201,60 @@ else if (child.getVisibility () != GONE)
|
||||
}
|
||||
}
|
||||
|
||||
public void
|
||||
public synchronized void
|
||||
damageRect (Rect damageRect)
|
||||
{
|
||||
damageRegion.union (damageRect);
|
||||
}
|
||||
|
||||
public void
|
||||
/* This method is called from both the UI thread and the Emacs
|
||||
thread. */
|
||||
|
||||
public synchronized void
|
||||
swapBuffers (boolean force)
|
||||
{
|
||||
Bitmap back;
|
||||
Canvas canvas;
|
||||
Rect damageRect;
|
||||
Bitmap bitmap;
|
||||
|
||||
if (damageRegion.isEmpty ())
|
||||
return;
|
||||
|
||||
if (!surfaceView.isCreated ())
|
||||
return;
|
||||
bitmap = getBitmap ();
|
||||
|
||||
if (bitmap == null)
|
||||
return;
|
||||
/* Emacs must take the following lock to ensure the access to the
|
||||
canvas occurs with the surface created. Otherwise, Android
|
||||
will throttle calls to lockCanvas. */
|
||||
|
||||
/* Lock the canvas with the specified damage. */
|
||||
damageRect = damageRegion.getBounds ();
|
||||
canvas = surfaceView.lockCanvas (damageRect);
|
||||
synchronized (surfaceView.surfaceChangeLock)
|
||||
{
|
||||
damageRect = damageRegion.getBounds ();
|
||||
|
||||
/* Return if locking the canvas failed. */
|
||||
if (canvas == null)
|
||||
return;
|
||||
if (!surfaceView.isCreated ())
|
||||
return;
|
||||
|
||||
/* Copy from the back buffer to the canvas. If damageRect was
|
||||
made empty, then draw the entire back buffer. */
|
||||
if (bitmap == null)
|
||||
return;
|
||||
|
||||
if (damageRect.isEmpty ())
|
||||
canvas.drawBitmap (bitmap, 0f, 0f, paint);
|
||||
else
|
||||
canvas.drawBitmap (bitmap, damageRect, damageRect, paint);
|
||||
/* Lock the canvas with the specified damage. */
|
||||
canvas = surfaceView.lockCanvas (damageRect);
|
||||
|
||||
/* Unlock the canvas and clear the damage. */
|
||||
surfaceView.unlockCanvasAndPost (canvas);
|
||||
damageRegion.setEmpty ();
|
||||
/* Return if locking the canvas failed. */
|
||||
if (canvas == null)
|
||||
return;
|
||||
|
||||
/* Copy from the back buffer to the canvas. If damageRect was
|
||||
made empty, then draw the entire back buffer. */
|
||||
|
||||
if (damageRect.isEmpty ())
|
||||
canvas.drawBitmap (bitmap, 0f, 0f, paint);
|
||||
else
|
||||
canvas.drawBitmap (bitmap, damageRect, damageRect, paint);
|
||||
|
||||
/* Unlock the canvas and clear the damage. */
|
||||
surfaceView.unlockCanvasAndPost (canvas);
|
||||
damageRegion.setEmpty ();
|
||||
}
|
||||
}
|
||||
|
||||
public void
|
||||
@ -241,4 +296,18 @@ else if (child.getVisibility () != GONE)
|
||||
super.onFocusChanged (gainFocus, direction,
|
||||
previouslyFocusedRect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean
|
||||
onGenericMotionEvent (MotionEvent motion)
|
||||
{
|
||||
return window.onSomeKindOfMotionEvent (motion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean
|
||||
onTouchEvent (MotionEvent motion)
|
||||
{
|
||||
return window.onSomeKindOfMotionEvent (motion);
|
||||
}
|
||||
};
|
||||
|
@ -31,8 +31,13 @@
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.InputDevice;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
/* This defines a window, which is a handle. Windows represent a
|
||||
rectangular subset of the screen with their own contents.
|
||||
@ -68,6 +73,10 @@ public class EmacsWindow extends EmacsHandleObject
|
||||
window background. */
|
||||
private EmacsGC scratchGC;
|
||||
|
||||
/* The button state and keyboard modifier mask at the time of the
|
||||
last button press or release event. */
|
||||
private int lastButtonState, lastModifiers;
|
||||
|
||||
public
|
||||
EmacsWindow (short handle, final EmacsWindow parent, int x, int y,
|
||||
int width, int height)
|
||||
@ -212,6 +221,7 @@ public class EmacsWindow extends EmacsHandleObject
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
view.mustReportLayout = true;
|
||||
view.requestLayout ();
|
||||
}
|
||||
});
|
||||
@ -224,6 +234,8 @@ public class EmacsWindow extends EmacsHandleObject
|
||||
{
|
||||
rect.right = rect.left + width;
|
||||
rect.bottom = rect.top + height;
|
||||
|
||||
requestViewLayout ();
|
||||
}
|
||||
}
|
||||
|
||||
@ -279,17 +291,7 @@ public class EmacsWindow extends EmacsHandleObject
|
||||
public Canvas
|
||||
lockCanvas ()
|
||||
{
|
||||
if (view.canvas != null)
|
||||
return view.canvas;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void
|
||||
unlockCanvas ()
|
||||
{
|
||||
|
||||
return view.getCanvas ();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -302,17 +304,7 @@ public class EmacsWindow extends EmacsHandleObject
|
||||
public void
|
||||
swapBuffers ()
|
||||
{
|
||||
/* Before calling swapBuffers, make sure to flush the paint
|
||||
queue. */
|
||||
EmacsService.SERVICE.flushPaintQueue ();
|
||||
view.post (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
view.swapBuffers ();
|
||||
}
|
||||
});
|
||||
view.swapBuffers ();
|
||||
}
|
||||
|
||||
public void
|
||||
@ -337,7 +329,7 @@ public class EmacsWindow extends EmacsHandleObject
|
||||
public Bitmap
|
||||
getBitmap ()
|
||||
{
|
||||
return view.bitmap;
|
||||
return view.getBitmap ();
|
||||
}
|
||||
|
||||
public void
|
||||
@ -357,6 +349,7 @@ public class EmacsWindow extends EmacsHandleObject
|
||||
recognized as an ASCII key press
|
||||
event. */
|
||||
event.getUnicodeChar (state));
|
||||
lastModifiers = event.getModifiers ();
|
||||
}
|
||||
|
||||
public void
|
||||
@ -372,6 +365,7 @@ public class EmacsWindow extends EmacsHandleObject
|
||||
event.getModifiers (),
|
||||
keyCode,
|
||||
event.getUnicodeChar (state));
|
||||
lastModifiers = event.getModifiers ();
|
||||
}
|
||||
|
||||
public void
|
||||
@ -386,4 +380,105 @@ public class EmacsWindow extends EmacsHandleObject
|
||||
/* Destroy the associated frame when the activity is detached. */
|
||||
EmacsNative.sendWindowAction (this.handle, 0);
|
||||
}
|
||||
|
||||
/* Look through the button state to determine what button EVENT was
|
||||
generated from. DOWN is true if EVENT is a button press event,
|
||||
false otherwise. Value is the X number of the button. */
|
||||
|
||||
private int
|
||||
whatButtonWasIt (MotionEvent event, boolean down)
|
||||
{
|
||||
int eventState, notIn;
|
||||
|
||||
if (Build.VERSION.SDK_INT
|
||||
< Build.VERSION_CODES.ICE_CREAM_SANDWICH)
|
||||
/* Earlier versions of Android only support one mouse
|
||||
button. */
|
||||
return 1;
|
||||
|
||||
eventState = event.getButtonState ();
|
||||
notIn = (down ? eventState & ~lastButtonState
|
||||
: lastButtonState & ~eventState);
|
||||
|
||||
if ((notIn & MotionEvent.BUTTON_PRIMARY) != 0)
|
||||
return 1;
|
||||
|
||||
if ((notIn & MotionEvent.BUTTON_SECONDARY) != 0)
|
||||
return 3;
|
||||
|
||||
if ((notIn & MotionEvent.BUTTON_TERTIARY) != 0)
|
||||
return 2;
|
||||
|
||||
/* Not a real value. */
|
||||
return 4;
|
||||
}
|
||||
|
||||
public boolean
|
||||
onSomeKindOfMotionEvent (MotionEvent event)
|
||||
{
|
||||
if (!event.isFromSource (InputDevice.SOURCE_CLASS_POINTER))
|
||||
return false;
|
||||
|
||||
switch (event.getAction ())
|
||||
{
|
||||
case MotionEvent.ACTION_HOVER_ENTER:
|
||||
EmacsNative.sendEnterNotify (this.handle, (int) event.getX (),
|
||||
(int) event.getY (),
|
||||
event.getEventTime ());
|
||||
return true;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
case MotionEvent.ACTION_HOVER_MOVE:
|
||||
EmacsNative.sendMotionNotify (this.handle, (int) event.getX (),
|
||||
(int) event.getY (),
|
||||
event.getEventTime ());
|
||||
return true;
|
||||
|
||||
case MotionEvent.ACTION_HOVER_EXIT:
|
||||
EmacsNative.sendLeaveNotify (this.handle, (int) event.getX (),
|
||||
(int) event.getY (),
|
||||
event.getEventTime ());
|
||||
return true;
|
||||
|
||||
case MotionEvent.ACTION_BUTTON_PRESS:
|
||||
/* Find the button which was pressed. */
|
||||
EmacsNative.sendButtonPress (this.handle, (int) event.getX (),
|
||||
(int) event.getY (),
|
||||
event.getEventTime (),
|
||||
lastModifiers,
|
||||
whatButtonWasIt (event, true));
|
||||
|
||||
if (Build.VERSION.SDK_INT
|
||||
< Build.VERSION_CODES.ICE_CREAM_SANDWICH)
|
||||
return true;
|
||||
|
||||
lastButtonState = event.getButtonState ();
|
||||
return true;
|
||||
|
||||
case MotionEvent.ACTION_BUTTON_RELEASE:
|
||||
/* Find the button which was released. */
|
||||
EmacsNative.sendButtonRelease (this.handle, (int) event.getX (),
|
||||
(int) event.getY (),
|
||||
event.getEventTime (),
|
||||
lastModifiers,
|
||||
whatButtonWasIt (event, false));
|
||||
|
||||
if (Build.VERSION.SDK_INT
|
||||
< Build.VERSION_CODES.ICE_CREAM_SANDWICH)
|
||||
return true;
|
||||
|
||||
lastButtonState = event.getButtonState ();
|
||||
return true;
|
||||
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case MotionEvent.ACTION_UP:
|
||||
/* Emacs must return true even though touch events are not yet
|
||||
handled, because the value of this function is used by the
|
||||
system to decide whether or not Emacs gets ACTION_MOVE
|
||||
events. */
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user