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.Rect;
|
||||||
import android.graphics.Xfermode;
|
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 static Xfermode overAlu;
|
||||||
private EmacsDrawable destination, source;
|
|
||||||
private EmacsGC immutableGC;
|
|
||||||
private static Xfermode xorAlu, srcInAlu, overAlu;
|
|
||||||
|
|
||||||
static
|
static
|
||||||
{
|
{
|
||||||
overAlu = new PorterDuffXfermode (Mode.SRC_OVER);
|
overAlu = new PorterDuffXfermode (Mode.SRC_OVER);
|
||||||
xorAlu = new PorterDuffXfermode (Mode.XOR);
|
|
||||||
srcInAlu = new PorterDuffXfermode (Mode.SRC_IN);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public
|
private static void
|
||||||
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
|
|
||||||
insetRectBy (Rect rect, int left, int top, int right,
|
insetRectBy (Rect rect, int left, int top, int right,
|
||||||
int bottom)
|
int bottom)
|
||||||
{
|
{
|
||||||
@ -84,30 +46,38 @@ public class EmacsCopyArea implements EmacsPaintReq
|
|||||||
rect.bottom -= bottom;
|
rect.bottom -= bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public static void
|
||||||
public EmacsGC
|
perform (EmacsDrawable source, EmacsGC gc,
|
||||||
getGC ()
|
EmacsDrawable destination,
|
||||||
|
int src_x, int src_y, int width, int height,
|
||||||
|
int dest_x, int dest_y)
|
||||||
{
|
{
|
||||||
return immutableGC;
|
int i;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void
|
|
||||||
paintTo (Canvas canvas, Paint paint, EmacsGC immutableGC)
|
|
||||||
{
|
|
||||||
int alu;
|
|
||||||
Bitmap bitmap;
|
Bitmap bitmap;
|
||||||
Paint maskPaint;
|
Paint maskPaint, paint;
|
||||||
Canvas maskCanvas;
|
Canvas maskCanvas, canvas;
|
||||||
Bitmap srcBitmap, maskBitmap, clipBitmap;
|
Bitmap srcBitmap, maskBitmap, clipBitmap;
|
||||||
Rect rect, maskRect, srcRect, dstRect, maskDestRect;
|
Rect rect, maskRect, srcRect, dstRect, maskDestRect;
|
||||||
boolean needFill;
|
boolean needFill;
|
||||||
|
|
||||||
/* TODO implement stippling. */
|
/* TODO implement stippling. */
|
||||||
if (immutableGC.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
||||||
return;
|
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
|
/* A copy must be created or drawBitmap could end up overwriting
|
||||||
itself. */
|
itself. */
|
||||||
@ -137,14 +107,10 @@ public class EmacsCopyArea implements EmacsPaintReq
|
|||||||
if (src_y + height > srcBitmap.getHeight ())
|
if (src_y + height > srcBitmap.getHeight ())
|
||||||
height = srcBitmap.getHeight () - src_y;
|
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)
|
if (gc.clip_mask == null)
|
||||||
paint.setXfermode (null);
|
|
||||||
else
|
|
||||||
paint.setXfermode (xorAlu);
|
|
||||||
|
|
||||||
if (immutableGC.clip_mask == null)
|
|
||||||
{
|
{
|
||||||
bitmap = Bitmap.createBitmap (srcBitmap,
|
bitmap = Bitmap.createBitmap (srcBitmap,
|
||||||
src_x, src_y, width,
|
src_x, src_y, width,
|
||||||
@ -156,17 +122,17 @@ public class EmacsCopyArea implements EmacsPaintReq
|
|||||||
/* Drawing with a clip mask involves calculating the
|
/* Drawing with a clip mask involves calculating the
|
||||||
intersection of the clip mask with the dst rect, and
|
intersection of the clip mask with the dst rect, and
|
||||||
extrapolating the corresponding part of the src rect. */
|
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,
|
dstRect = new Rect (dest_x, dest_y,
|
||||||
dest_x + width,
|
dest_x + width,
|
||||||
dest_y + height);
|
dest_y + height);
|
||||||
maskRect = new Rect (immutableGC.clip_x_origin,
|
maskRect = new Rect (gc.clip_x_origin,
|
||||||
immutableGC.clip_y_origin,
|
gc.clip_y_origin,
|
||||||
(immutableGC.clip_x_origin
|
(gc.clip_x_origin
|
||||||
+ clipBitmap.getWidth ()),
|
+ clipBitmap.getWidth ()),
|
||||||
(immutableGC.clip_y_origin
|
(gc.clip_y_origin
|
||||||
+ clipBitmap.getHeight ()));
|
+ clipBitmap.getHeight ()));
|
||||||
clipBitmap = immutableGC.clip_mask.bitmap;
|
clipBitmap = gc.clip_mask.bitmap;
|
||||||
|
|
||||||
if (!maskRect.setIntersect (dstRect, maskRect))
|
if (!maskRect.setIntersect (dstRect, maskRect))
|
||||||
/* There is no intersection between the clip mask and the
|
/* 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. */
|
/* Draw the mask onto the maskBitmap. */
|
||||||
maskCanvas = new Canvas (maskBitmap);
|
maskCanvas = new Canvas (maskBitmap);
|
||||||
maskRect.offset (-immutableGC.clip_x_origin,
|
maskPaint = new Paint ();
|
||||||
-immutableGC.clip_y_origin);
|
maskRect.offset (-gc.clip_x_origin,
|
||||||
maskCanvas.drawBitmap (immutableGC.clip_mask.bitmap,
|
-gc.clip_y_origin);
|
||||||
maskRect, new Rect (0, 0,
|
maskCanvas.drawBitmap (gc.clip_mask.bitmap,
|
||||||
maskRect.width (),
|
maskRect,
|
||||||
maskRect.height ()),
|
new Rect (0, 0,
|
||||||
paint);
|
maskRect.width (),
|
||||||
maskRect.offset (immutableGC.clip_x_origin,
|
maskRect.height ()),
|
||||||
immutableGC.clip_y_origin);
|
maskPaint);
|
||||||
|
maskRect.offset (gc.clip_x_origin,
|
||||||
|
gc.clip_y_origin);
|
||||||
|
|
||||||
/* 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.setXfermode (EmacsGC.srcInAlu);
|
||||||
maskPaint.setXfermode (srcInAlu);
|
|
||||||
|
|
||||||
/* Draw the source. */
|
/* Draw the source. */
|
||||||
maskDestRect = new Rect (0, 0, srcRect.width (),
|
maskDestRect = new Rect (0, 0, srcRect.width (),
|
||||||
@ -215,6 +182,10 @@ maskRect, new Rect (0, 0,
|
|||||||
/* Finally, draw the mask bitmap to the destination. */
|
/* Finally, draw the mask bitmap to the destination. */
|
||||||
paint.setXfermode (overAlu);
|
paint.setXfermode (overAlu);
|
||||||
canvas.drawBitmap (maskBitmap, null, maskRect, paint);
|
canvas.drawBitmap (maskBitmap, null, maskRect, paint);
|
||||||
|
gc.resetXfermode ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
canvas.restore ();
|
||||||
|
destination.damageRect (rect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,109 +29,49 @@
|
|||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.Xfermode;
|
import android.graphics.Xfermode;
|
||||||
|
|
||||||
public class EmacsDrawLine implements EmacsPaintReq
|
public class EmacsDrawLine
|
||||||
{
|
{
|
||||||
private int x, y, x2, y2;
|
public static void
|
||||||
private EmacsDrawable drawable;
|
perform (EmacsDrawable drawable, EmacsGC gc,
|
||||||
private EmacsGC immutableGC;
|
int x, int y, int x2, int y2)
|
||||||
private static Xfermode xorAlu, srcInAlu;
|
|
||||||
|
|
||||||
static
|
|
||||||
{
|
{
|
||||||
xorAlu = new PorterDuffXfermode (Mode.XOR);
|
Rect rect;
|
||||||
srcInAlu = new PorterDuffXfermode (Mode.SRC_IN);
|
Canvas canvas;
|
||||||
};
|
Paint paint;
|
||||||
|
int i;
|
||||||
|
|
||||||
public
|
/* TODO implement stippling. */
|
||||||
EmacsDrawLine (EmacsDrawable drawable, int x, int y,
|
if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
||||||
int x2, int y2, EmacsGC immutableGC)
|
return;
|
||||||
{
|
|
||||||
this.drawable = drawable;
|
|
||||||
this.x = x;
|
|
||||||
this.y = y;
|
|
||||||
this.x2 = x2;
|
|
||||||
this.y2 = y2;
|
|
||||||
this.immutableGC = immutableGC;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
paint = gc.gcPaint;
|
||||||
public Rect
|
rect = new Rect (Math.min (x, x2 + 1),
|
||||||
getRect ()
|
|
||||||
{
|
|
||||||
return new Rect (Math.min (x, x2 + 1),
|
|
||||||
Math.min (y, y2 + 1),
|
Math.min (y, y2 + 1),
|
||||||
Math.max (x2 + 1, x),
|
Math.max (x2 + 1, x),
|
||||||
Math.max (y2 + 1, y));
|
Math.max (y2 + 1, y));
|
||||||
}
|
canvas = drawable.lockCanvas ();
|
||||||
|
|
||||||
@Override
|
if (canvas == null)
|
||||||
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)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
alu = immutableGC.function;
|
canvas.save ();
|
||||||
rect = getRect ();
|
|
||||||
width = rect.width ();
|
if (gc.real_clip_rects != null)
|
||||||
height = rect.height ();
|
{
|
||||||
|
for (i = 0; i < gc.real_clip_rects.length; ++i)
|
||||||
|
canvas.clipRect (gc.real_clip_rects[i]);
|
||||||
|
}
|
||||||
|
|
||||||
paint.setStyle (Paint.Style.STROKE);
|
paint.setStyle (Paint.Style.STROKE);
|
||||||
|
|
||||||
if (alu == EmacsGC.GC_COPY)
|
if (gc.clip_mask == null)
|
||||||
paint.setXfermode (null);
|
canvas.drawLine ((float) x, (float) y,
|
||||||
else
|
(float) x2, (float) y2,
|
||||||
paint.setXfermode (xorAlu);
|
paint);
|
||||||
|
|
||||||
if (immutableGC.clip_mask == null)
|
/* DrawLine with clip mask not implemented; it is not used by
|
||||||
{
|
Emacs. */
|
||||||
paint.setColor (immutableGC.foreground | 0xff000000);
|
canvas.restore ();
|
||||||
canvas.drawLine ((float) x, (float) y,
|
drawable.damageRect (rect);
|
||||||
(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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,12 +19,13 @@
|
|||||||
|
|
||||||
package org.gnu.emacs;
|
package org.gnu.emacs;
|
||||||
|
|
||||||
public class EmacsDrawPoint extends EmacsDrawRectangle
|
public class EmacsDrawPoint
|
||||||
{
|
{
|
||||||
public
|
public static void
|
||||||
EmacsDrawPoint (EmacsDrawable drawable, int x, int y,
|
perform (EmacsDrawable drawable,
|
||||||
EmacsGC immutableGC)
|
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.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.Xfermode;
|
|
||||||
|
|
||||||
public class EmacsDrawRectangle implements EmacsPaintReq
|
import android.util.Log;
|
||||||
|
|
||||||
|
public class EmacsDrawRectangle
|
||||||
{
|
{
|
||||||
private int x, y, width, height;
|
public static void
|
||||||
private EmacsDrawable drawable;
|
perform (EmacsDrawable drawable, EmacsGC gc,
|
||||||
private EmacsGC immutableGC;
|
int x, int y, int width, int height)
|
||||||
private static Xfermode xorAlu, srcInAlu;
|
|
||||||
|
|
||||||
static
|
|
||||||
{
|
{
|
||||||
xorAlu = new PorterDuffXfermode (Mode.XOR);
|
int i;
|
||||||
srcInAlu = new PorterDuffXfermode (Mode.SRC_IN);
|
Paint maskPaint, paint;
|
||||||
};
|
|
||||||
|
|
||||||
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;
|
|
||||||
Canvas maskCanvas;
|
Canvas maskCanvas;
|
||||||
Bitmap maskBitmap;
|
Bitmap maskBitmap;
|
||||||
Rect rect, srcRect;
|
Rect rect;
|
||||||
|
Rect maskRect, dstRect;
|
||||||
|
Canvas canvas;
|
||||||
|
Bitmap clipBitmap;
|
||||||
|
|
||||||
/* TODO implement stippling. */
|
/* TODO implement stippling. */
|
||||||
if (immutableGC.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
||||||
return;
|
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);
|
rect = new Rect (x, y, x + width, y + height);
|
||||||
|
|
||||||
paint.setStyle (Paint.Style.STROKE);
|
paint.setStyle (Paint.Style.STROKE);
|
||||||
paint.setStrokeWidth (1);
|
|
||||||
|
|
||||||
if (alu == EmacsGC.GC_COPY)
|
if (gc.clip_mask == null)
|
||||||
paint.setXfermode (null);
|
canvas.drawRect (rect, paint);
|
||||||
else
|
|
||||||
paint.setXfermode (xorAlu);
|
|
||||||
|
|
||||||
if (immutableGC.clip_mask == null)
|
|
||||||
{
|
|
||||||
paint.setColor (immutableGC.foreground | 0xff000000);
|
|
||||||
canvas.drawRect (rect, paint);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
maskPaint = new Paint ();
|
/* Drawing with a clip mask involves calculating the
|
||||||
maskBitmap
|
intersection of the clip mask with the dst rect, and
|
||||||
= immutableGC.clip_mask.bitmap.copy (Bitmap.Config.ARGB_8888,
|
extrapolating the corresponding part of the src rect. */
|
||||||
true);
|
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;
|
return;
|
||||||
|
|
||||||
maskPaint.setXfermode (srcInAlu);
|
/* Finally, create a temporary bitmap that is the size of
|
||||||
maskPaint.setColor (immutableGC.foreground | 0xff000000);
|
maskRect. */
|
||||||
|
|
||||||
|
maskBitmap
|
||||||
|
= Bitmap.createBitmap (maskRect.width (), maskRect.height (),
|
||||||
|
Bitmap.Config.ARGB_8888);
|
||||||
|
|
||||||
|
/* Draw the mask onto the maskBitmap. */
|
||||||
maskCanvas = new Canvas (maskBitmap);
|
maskCanvas = new Canvas (maskBitmap);
|
||||||
srcRect = new Rect (0, 0, maskBitmap.getWidth (),
|
maskRect.offset (-gc.clip_x_origin,
|
||||||
maskBitmap.getHeight ());
|
-gc.clip_y_origin);
|
||||||
maskCanvas.drawRect (srcRect, maskPaint);
|
maskCanvas.drawBitmap (gc.clip_mask.bitmap,
|
||||||
canvas.drawBitmap (maskBitmap, srcRect, rect, paint);
|
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 interface EmacsDrawable
|
||||||
{
|
{
|
||||||
public Canvas lockCanvas ();
|
public Canvas lockCanvas ();
|
||||||
public void unlockCanvas ();
|
|
||||||
public void damageRect (Rect damageRect);
|
public void damageRect (Rect damageRect);
|
||||||
public Bitmap getBitmap ();
|
public Bitmap getBitmap ();
|
||||||
public boolean isDestroyed ();
|
public boolean isDestroyed ();
|
||||||
|
@ -26,34 +26,35 @@
|
|||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Path;
|
import android.graphics.Path;
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
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;
|
|
||||||
|
|
||||||
public class EmacsFillPolygon implements EmacsPaintReq
|
public class EmacsFillPolygon
|
||||||
{
|
{
|
||||||
private EmacsDrawable drawable;
|
public static void
|
||||||
private EmacsGC immutableGC;
|
perform (EmacsDrawable drawable, EmacsGC gc, Point points[])
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
|
Canvas canvas;
|
||||||
|
Path path;
|
||||||
|
Paint paint;
|
||||||
|
Rect rect;
|
||||||
|
RectF rectF;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
this.drawable = drawable;
|
canvas = drawable.lockCanvas ();
|
||||||
this.immutableGC = immutableGC;
|
|
||||||
|
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. */
|
/* Build the path from the given array of points. */
|
||||||
path = new Path ();
|
path = new Path ();
|
||||||
@ -67,84 +68,25 @@ public class EmacsFillPolygon implements EmacsPaintReq
|
|||||||
|
|
||||||
path.close ();
|
path.close ();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
/* Compute the damage rectangle. */
|
||||||
public Rect
|
rectF = new RectF (0, 0, 0, 0);
|
||||||
getRect ()
|
path.computeBounds (rectF, true);
|
||||||
{
|
|
||||||
RectF rect;
|
|
||||||
|
|
||||||
rect = new RectF (0, 0, 0, 0);
|
rect = new Rect ((int) Math.floor (rectF.left),
|
||||||
path.computeBounds (rect, true);
|
(int) Math.floor (rectF.top),
|
||||||
|
(int) Math.ceil (rectF.right),
|
||||||
return new Rect ((int) Math.floor (rect.left),
|
(int) Math.ceil (rectF.bottom));
|
||||||
(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);
|
|
||||||
|
|
||||||
paint.setStyle (Paint.Style.FILL);
|
paint.setStyle (Paint.Style.FILL);
|
||||||
|
|
||||||
if (immutableGC.clip_mask == null)
|
if (gc.clip_mask == null)
|
||||||
{
|
canvas.drawPath (path, paint);
|
||||||
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 (maskBitmap == null)
|
canvas.restore ();
|
||||||
return;
|
drawable.damageRect (rect);
|
||||||
|
|
||||||
maskPaint.setXfermode (srcInAlu);
|
/* FillPolygon with clip mask not implemented; it is not used by
|
||||||
maskPaint.setColor (immutableGC.foreground | 0xff000000);
|
Emacs. */
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,108 +22,102 @@
|
|||||||
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.Xfermode;
|
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class EmacsFillRectangle implements EmacsPaintReq
|
public class EmacsFillRectangle
|
||||||
{
|
{
|
||||||
private int x, y, width, height;
|
public static void
|
||||||
private EmacsDrawable drawable;
|
perform (EmacsDrawable drawable, EmacsGC gc,
|
||||||
private EmacsGC immutableGC;
|
int x, int y, int width, int height)
|
||||||
private static Xfermode xorAlu, srcInAlu;
|
|
||||||
|
|
||||||
static
|
|
||||||
{
|
{
|
||||||
xorAlu = new PorterDuffXfermode (Mode.XOR);
|
int i;
|
||||||
srcInAlu = new PorterDuffXfermode (Mode.SRC_IN);
|
Paint maskPaint, paint;
|
||||||
};
|
|
||||||
|
|
||||||
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;
|
|
||||||
Canvas maskCanvas;
|
Canvas maskCanvas;
|
||||||
Bitmap maskBitmap;
|
Bitmap maskBitmap;
|
||||||
Rect rect, srcRect;
|
Rect rect;
|
||||||
|
Rect maskRect, dstRect;
|
||||||
|
Canvas canvas;
|
||||||
|
Bitmap clipBitmap;
|
||||||
|
|
||||||
/* TODO implement stippling. */
|
/* TODO implement stippling. */
|
||||||
if (immutableGC.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
alu = immutableGC.function;
|
canvas = drawable.lockCanvas ();
|
||||||
rect = getRect ();
|
|
||||||
|
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);
|
paint.setStyle (Paint.Style.FILL);
|
||||||
|
|
||||||
if (alu == EmacsGC.GC_COPY)
|
if (gc.clip_mask == null)
|
||||||
paint.setXfermode (null);
|
canvas.drawRect (rect, paint);
|
||||||
else
|
|
||||||
paint.setXfermode (xorAlu);
|
|
||||||
|
|
||||||
if (immutableGC.clip_mask == null)
|
|
||||||
{
|
|
||||||
paint.setColor (immutableGC.foreground | 0xff000000);
|
|
||||||
canvas.drawRect (rect, paint);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
maskPaint = new Paint ();
|
/* Drawing with a clip mask involves calculating the
|
||||||
maskBitmap
|
intersection of the clip mask with the dst rect, and
|
||||||
= immutableGC.clip_mask.bitmap.copy (Bitmap.Config.ARGB_8888,
|
extrapolating the corresponding part of the src rect. */
|
||||||
true);
|
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;
|
return;
|
||||||
|
|
||||||
maskPaint.setXfermode (srcInAlu);
|
/* Finally, create a temporary bitmap that is the size of
|
||||||
maskPaint.setColor (immutableGC.foreground | 0xff000000);
|
maskRect. */
|
||||||
|
|
||||||
|
maskBitmap
|
||||||
|
= Bitmap.createBitmap (maskRect.width (), maskRect.height (),
|
||||||
|
Bitmap.Config.ARGB_8888);
|
||||||
|
|
||||||
|
/* Draw the mask onto the maskBitmap. */
|
||||||
maskCanvas = new Canvas (maskBitmap);
|
maskCanvas = new Canvas (maskBitmap);
|
||||||
srcRect = new Rect (0, 0, maskBitmap.getWidth (),
|
maskRect.offset (-gc.clip_x_origin,
|
||||||
maskBitmap.getHeight ());
|
-gc.clip_y_origin);
|
||||||
maskCanvas.drawRect (srcRect, maskPaint);
|
maskCanvas.drawBitmap (gc.clip_mask.bitmap,
|
||||||
canvas.drawBitmap (maskBitmap, srcRect, rect, paint);
|
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
|
public static EmacsFontDriver
|
||||||
createFontDriver ()
|
createFontDriver ()
|
||||||
{
|
{
|
||||||
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
||||||
return new EmacsSdk23FontDriver ();
|
return new EmacsSdk23FontDriver ();
|
||||||
|
|
||||||
return new EmacsSdk7FontDriver ();
|
return new EmacsSdk7FontDriver ();
|
||||||
|
@ -20,6 +20,11 @@
|
|||||||
package org.gnu.emacs;
|
package org.gnu.emacs;
|
||||||
|
|
||||||
import android.graphics.Rect;
|
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
|
/* X like graphics context structures. Keep the enums in synch with
|
||||||
androidgui.h! */
|
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_SOLID = 0;
|
||||||
public static final int GC_FILL_OPAQUE_STIPPLED = 1;
|
public static final int GC_FILL_OPAQUE_STIPPLED = 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;
|
||||||
public int ts_origin_x, ts_origin_y;
|
public int ts_origin_x, ts_origin_y;
|
||||||
public Rect clip_rects[];
|
public Rect clip_rects[], real_clip_rects[];
|
||||||
public EmacsPixmap clip_mask, stipple;
|
public EmacsPixmap clip_mask, stipple;
|
||||||
private boolean dirty;
|
public Paint gcPaint;
|
||||||
private EmacsGC immutableGC;
|
|
||||||
|
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. */
|
||||||
|
|
||||||
@ -55,62 +67,41 @@ public class EmacsGC extends EmacsHandleObject
|
|||||||
fill_style = GC_FILL_SOLID;
|
fill_style = GC_FILL_SOLID;
|
||||||
function = GC_COPY;
|
function = GC_COPY;
|
||||||
foreground = 0;
|
foreground = 0;
|
||||||
background = 0xffffffff;
|
background = 0xffffff;
|
||||||
|
gcPaint = new Paint ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public
|
/* Mark this GC as dirty. Apply parameters to the paint and
|
||||||
EmacsGC (EmacsGC source)
|
recompute real_clip_rects. */
|
||||||
{
|
|
||||||
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. */
|
|
||||||
|
|
||||||
public void
|
public void
|
||||||
markDirty ()
|
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
|
public void
|
||||||
immutableGC ()
|
resetXfermode ()
|
||||||
{
|
{
|
||||||
if (immutableGC == null || dirty)
|
gcPaint.setXfermode (function == GC_XOR
|
||||||
{
|
? xorAlu : srcInAlu);
|
||||||
immutableGC = new EmacsGC (this);
|
}
|
||||||
dirty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return immutableGC;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
@ -79,6 +79,28 @@ public static native void sendKeyRelease (short window, long time, int state,
|
|||||||
/* Send an ANDROID_WINDOW_ACTION event. */
|
/* Send an ANDROID_WINDOW_ACTION event. */
|
||||||
public static native void sendWindowAction (short window, int action);
|
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
|
static
|
||||||
{
|
{
|
||||||
System.loadLibrary ("emacs");
|
System.loadLibrary ("emacs");
|
||||||
|
@ -93,6 +93,8 @@ public class EmacsPixmap extends EmacsHandleObject
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bitmap.eraseColor (0xff000000);
|
||||||
|
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
this.depth = depth;
|
this.depth = depth;
|
||||||
@ -108,13 +110,6 @@ public class EmacsPixmap extends EmacsHandleObject
|
|||||||
return canvas;
|
return canvas;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void
|
|
||||||
unlockCanvas ()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void
|
public void
|
||||||
damageRect (Rect damageRect)
|
damageRect (Rect damageRect)
|
||||||
|
@ -20,9 +20,80 @@
|
|||||||
package org.gnu.emacs;
|
package org.gnu.emacs;
|
||||||
|
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
|
||||||
public class EmacsSdk23FontDriver extends EmacsSdk7FontDriver
|
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
|
@Override
|
||||||
public int
|
public int
|
||||||
hasChar (FontSpec font, char charCode)
|
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 String[] fontFamilyList;
|
||||||
private Sdk7Typeface[] typefaceList;
|
private Sdk7Typeface[] typefaceList;
|
||||||
private Sdk7Typeface fallbackTypeface;
|
private Sdk7Typeface fallbackTypeface;
|
||||||
@ -498,14 +411,11 @@ private class Sdk7DrawString implements EmacsPaintReq
|
|||||||
Paint paint, Rect bounds)
|
Paint paint, Rect bounds)
|
||||||
{
|
{
|
||||||
char[] text;
|
char[] text;
|
||||||
float[] width;
|
|
||||||
|
|
||||||
text = new char[1];
|
text = new char[1];
|
||||||
text[0] = (char) code;
|
text[0] = (char) code;
|
||||||
|
|
||||||
paint.getTextBounds (text, 0, 1, bounds);
|
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.
|
/* bounds is the bounding box of the glyph corresponding to CODE.
|
||||||
Translate these into XCharStruct values.
|
Translate these into XCharStruct values.
|
||||||
@ -526,7 +436,7 @@ raster. descent is the distance (once again counting
|
|||||||
metrics.rbearing = (short) bounds.right;
|
metrics.rbearing = (short) bounds.right;
|
||||||
metrics.ascent = (short) -bounds.top;
|
metrics.ascent = (short) -bounds.top;
|
||||||
metrics.descent = (short) bounds.bottom;
|
metrics.descent = (short) bounds.bottom;
|
||||||
metrics.width = (short) Math.round (width[0]);
|
metrics.width = (short) paint.measureText ("" + text[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -563,7 +473,8 @@ else if (code.length == 1)
|
|||||||
for (i = 0; i < code.length; ++i)
|
for (i = 0; i < code.length; ++i)
|
||||||
text[i] = (char) code[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);
|
width = paintCache.measureText (text, 0, code.length);
|
||||||
|
|
||||||
fontMetrics.lbearing = (short) boundsCache.left;
|
fontMetrics.lbearing = (short) boundsCache.left;
|
||||||
@ -587,11 +498,12 @@ else if (code.length == 1)
|
|||||||
int[] chars, int x, int y, int backgroundWidth,
|
int[] chars, int x, int y, int backgroundWidth,
|
||||||
boolean withBackground)
|
boolean withBackground)
|
||||||
{
|
{
|
||||||
Rect backgroundRect;
|
Rect backgroundRect, bounds;
|
||||||
Sdk7FontObject sdk7FontObject;
|
Sdk7FontObject sdk7FontObject;
|
||||||
Sdk7DrawString op;
|
|
||||||
char[] charsArray;
|
char[] charsArray;
|
||||||
int i;
|
int i;
|
||||||
|
Canvas canvas;
|
||||||
|
Paint paint;
|
||||||
|
|
||||||
sdk7FontObject = (Sdk7FontObject) fontObject;
|
sdk7FontObject = (Sdk7FontObject) fontObject;
|
||||||
charsArray = new char[chars.length];
|
charsArray = new char[chars.length];
|
||||||
@ -605,12 +517,41 @@ else if (code.length == 1)
|
|||||||
backgroundRect.right = x + backgroundWidth;
|
backgroundRect.right = x + backgroundWidth;
|
||||||
backgroundRect.bottom = y + sdk7FontObject.descent;
|
backgroundRect.bottom = y + sdk7FontObject.descent;
|
||||||
|
|
||||||
op = new Sdk7DrawString (sdk7FontObject, charsArray,
|
canvas = drawable.lockCanvas ();
|
||||||
gc.immutableGC (), drawable,
|
|
||||||
withBackground,
|
|
||||||
backgroundRect, x, y);
|
|
||||||
|
|
||||||
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;
|
return 1;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
package org.gnu.emacs;
|
package org.gnu.emacs;
|
||||||
|
|
||||||
import java.lang.Runnable;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -59,7 +58,6 @@ public class EmacsService extends Service
|
|||||||
|
|
||||||
private EmacsThread thread;
|
private EmacsThread thread;
|
||||||
private Handler handler;
|
private Handler handler;
|
||||||
private EmacsPaintQueue paintQueue;
|
|
||||||
|
|
||||||
/* Display metrics used by font backends. */
|
/* Display metrics used by font backends. */
|
||||||
public DisplayMetrics metrics;
|
public DisplayMetrics metrics;
|
||||||
@ -191,126 +189,42 @@ else if (apiLevel >= Build.VERSION_CODES.DONUT)
|
|||||||
return view.thing;
|
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
|
public void
|
||||||
fillRectangle (EmacsDrawable drawable, EmacsGC gc,
|
fillRectangle (EmacsDrawable drawable, EmacsGC gc,
|
||||||
int x, int y, int width, int height)
|
int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
EmacsPaintReq req;
|
EmacsFillRectangle.perform (drawable, gc, x, y,
|
||||||
|
width, height);
|
||||||
ensurePaintQueue ();
|
|
||||||
|
|
||||||
req = new EmacsFillRectangle (drawable, x, y,
|
|
||||||
width, height,
|
|
||||||
gc.immutableGC ());
|
|
||||||
paintQueue.appendPaintOperation (req);
|
|
||||||
checkFlush ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void
|
public void
|
||||||
fillPolygon (EmacsDrawable drawable, EmacsGC gc,
|
fillPolygon (EmacsDrawable drawable, EmacsGC gc,
|
||||||
Point points[])
|
Point points[])
|
||||||
{
|
{
|
||||||
EmacsPaintReq req;
|
EmacsFillPolygon.perform (drawable, gc, points);
|
||||||
|
|
||||||
ensurePaintQueue ();
|
|
||||||
|
|
||||||
req = new EmacsFillPolygon (drawable, points,
|
|
||||||
gc.immutableGC ());
|
|
||||||
paintQueue.appendPaintOperation (req);
|
|
||||||
checkFlush ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void
|
public void
|
||||||
drawRectangle (EmacsDrawable drawable, EmacsGC gc,
|
drawRectangle (EmacsDrawable drawable, EmacsGC gc,
|
||||||
int x, int y, int width, int height)
|
int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
EmacsPaintReq req;
|
EmacsDrawRectangle.perform (drawable, gc, x, y,
|
||||||
|
width, height);
|
||||||
ensurePaintQueue ();
|
|
||||||
|
|
||||||
req = new EmacsDrawRectangle (drawable, x, y,
|
|
||||||
width, height,
|
|
||||||
gc.immutableGC ());
|
|
||||||
paintQueue.appendPaintOperation (req);
|
|
||||||
checkFlush ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void
|
public void
|
||||||
drawLine (EmacsDrawable drawable, EmacsGC gc,
|
drawLine (EmacsDrawable drawable, EmacsGC gc,
|
||||||
int x, int y, int x2, int y2)
|
int x, int y, int x2, int y2)
|
||||||
{
|
{
|
||||||
EmacsPaintReq req;
|
EmacsDrawLine.perform (drawable, gc, x, y,
|
||||||
|
x2, y2);
|
||||||
ensurePaintQueue ();
|
|
||||||
|
|
||||||
req = new EmacsDrawLine (drawable, x, y,
|
|
||||||
x2, y2,
|
|
||||||
gc.immutableGC ());
|
|
||||||
paintQueue.appendPaintOperation (req);
|
|
||||||
checkFlush ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void
|
public void
|
||||||
drawPoint (EmacsDrawable drawable, EmacsGC gc,
|
drawPoint (EmacsDrawable drawable, EmacsGC gc,
|
||||||
int x, int y)
|
int x, int y)
|
||||||
{
|
{
|
||||||
EmacsPaintReq req;
|
EmacsDrawPoint.perform (drawable, gc, x, y);
|
||||||
|
|
||||||
ensurePaintQueue ();
|
|
||||||
|
|
||||||
req = new EmacsDrawPoint (drawable, x, y,
|
|
||||||
gc.immutableGC ());
|
|
||||||
paintQueue.appendPaintOperation (req);
|
|
||||||
checkFlush ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void
|
public void
|
||||||
@ -319,15 +233,9 @@ else if (apiLevel >= Build.VERSION_CODES.DONUT)
|
|||||||
int srcX, int srcY, int width, int height, int destX,
|
int srcX, int srcY, int width, int height, int destX,
|
||||||
int destY)
|
int destY)
|
||||||
{
|
{
|
||||||
EmacsPaintReq req;
|
EmacsCopyArea.perform (srcDrawable, gc, dstDrawable,
|
||||||
|
srcX, srcY, width, height, destX,
|
||||||
ensurePaintQueue ();
|
destY);
|
||||||
|
|
||||||
req = new EmacsCopyArea (srcDrawable, dstDrawable,
|
|
||||||
srcX, srcY, width, height, destX,
|
|
||||||
destY, gc.immutableGC ());
|
|
||||||
paintQueue.appendPaintOperation (req);
|
|
||||||
checkFlush ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void
|
public void
|
||||||
@ -342,12 +250,4 @@ else if (apiLevel >= Build.VERSION_CODES.DONUT)
|
|||||||
{
|
{
|
||||||
window.clearArea (x, y, width, height);
|
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 class EmacsSurfaceView extends SurfaceView
|
||||||
{
|
{
|
||||||
|
public Object surfaceChangeLock;
|
||||||
private boolean created;
|
private boolean created;
|
||||||
|
|
||||||
public
|
public
|
||||||
@ -36,33 +37,36 @@ public class EmacsSurfaceView extends SurfaceView
|
|||||||
{
|
{
|
||||||
super (view.getContext ());
|
super (view.getContext ());
|
||||||
|
|
||||||
|
surfaceChangeLock = new Object ();
|
||||||
|
|
||||||
getHolder ().addCallback (new SurfaceHolder.Callback () {
|
getHolder ().addCallback (new SurfaceHolder.Callback () {
|
||||||
@Override
|
@Override
|
||||||
public void
|
public void
|
||||||
surfaceChanged (SurfaceHolder holder, int format,
|
surfaceChanged (SurfaceHolder holder, int format,
|
||||||
int width, int height)
|
int width, int height)
|
||||||
{
|
{
|
||||||
/* Force a buffer swap now to get the contents of the Emacs
|
view.swapBuffers ();
|
||||||
view on screen. */
|
|
||||||
view.swapBuffers (true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void
|
public void
|
||||||
surfaceCreated (SurfaceHolder holder)
|
surfaceCreated (SurfaceHolder holder)
|
||||||
{
|
{
|
||||||
created = true;
|
synchronized (surfaceChangeLock)
|
||||||
|
{
|
||||||
/* Force a buffer swap now to get the contents of the Emacs
|
created = true;
|
||||||
view on screen. */
|
view.swapBuffers ();
|
||||||
view.swapBuffers (true);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void
|
public void
|
||||||
surfaceDestroyed (SurfaceHolder holder)
|
surfaceDestroyed (SurfaceHolder holder)
|
||||||
{
|
{
|
||||||
created = false;
|
synchronized (surfaceChangeLock)
|
||||||
|
{
|
||||||
|
created = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
|
import android.view.MotionEvent;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
@ -64,6 +65,14 @@ public class EmacsView extends ViewGroup
|
|||||||
/* The associated surface view. */
|
/* The associated surface view. */
|
||||||
private EmacsSurfaceView surfaceView;
|
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
|
public
|
||||||
EmacsView (EmacsWindow window)
|
EmacsView (EmacsWindow window)
|
||||||
{
|
{
|
||||||
@ -81,6 +90,43 @@ public class EmacsView extends ViewGroup
|
|||||||
addView (this.surfaceView);
|
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
|
@Override
|
||||||
protected void
|
protected void
|
||||||
onMeasure (int widthMeasureSpec, int heightMeasureSpec)
|
onMeasure (int widthMeasureSpec, int heightMeasureSpec)
|
||||||
@ -114,7 +160,7 @@ else if (MeasureSpec.getMode (heightMeasureSpec) == MeasureSpec.AT_MOST
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void
|
protected synchronized void
|
||||||
onLayout (boolean changed, int left, int top, int right,
|
onLayout (boolean changed, int left, int top, int right,
|
||||||
int bottom)
|
int bottom)
|
||||||
{
|
{
|
||||||
@ -122,19 +168,15 @@ else if (MeasureSpec.getMode (heightMeasureSpec) == MeasureSpec.AT_MOST
|
|||||||
View child;
|
View child;
|
||||||
Rect windowRect;
|
Rect windowRect;
|
||||||
|
|
||||||
if (changed)
|
if (changed || mustReportLayout)
|
||||||
{
|
{
|
||||||
|
mustReportLayout = false;
|
||||||
window.viewLayout (left, top, right, bottom);
|
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 ();
|
count = getChildCount ();
|
||||||
|
|
||||||
for (i = 0; i < count; ++i)
|
for (i = 0; i < count; ++i)
|
||||||
@ -159,47 +201,60 @@ else if (child.getVisibility () != GONE)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void
|
public synchronized void
|
||||||
damageRect (Rect damageRect)
|
damageRect (Rect damageRect)
|
||||||
{
|
{
|
||||||
damageRegion.union (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)
|
swapBuffers (boolean force)
|
||||||
{
|
{
|
||||||
Bitmap back;
|
|
||||||
Canvas canvas;
|
Canvas canvas;
|
||||||
Rect damageRect;
|
Rect damageRect;
|
||||||
|
Bitmap bitmap;
|
||||||
|
|
||||||
if (damageRegion.isEmpty ())
|
if (damageRegion.isEmpty ())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!surfaceView.isCreated ())
|
bitmap = getBitmap ();
|
||||||
return;
|
|
||||||
|
|
||||||
if (bitmap == null)
|
/* Emacs must take the following lock to ensure the access to the
|
||||||
return;
|
canvas occurs with the surface created. Otherwise, Android
|
||||||
|
will throttle calls to lockCanvas. */
|
||||||
|
|
||||||
/* Lock the canvas with the specified damage. */
|
synchronized (surfaceView.surfaceChangeLock)
|
||||||
damageRect = damageRegion.getBounds ();
|
{
|
||||||
canvas = surfaceView.lockCanvas (damageRect);
|
damageRect = damageRegion.getBounds ();
|
||||||
|
|
||||||
/* Return if locking the canvas failed. */
|
if (!surfaceView.isCreated ())
|
||||||
if (canvas == null)
|
return;
|
||||||
return;
|
|
||||||
|
|
||||||
/* Copy from the back buffer to the canvas. If damageRect was
|
if (bitmap == null)
|
||||||
made empty, then draw the entire back buffer. */
|
return;
|
||||||
|
|
||||||
if (damageRect.isEmpty ())
|
/* Lock the canvas with the specified damage. */
|
||||||
canvas.drawBitmap (bitmap, 0f, 0f, paint);
|
canvas = surfaceView.lockCanvas (damageRect);
|
||||||
else
|
|
||||||
canvas.drawBitmap (bitmap, damageRect, damageRect, paint);
|
|
||||||
|
|
||||||
/* Unlock the canvas and clear the damage. */
|
/* Return if locking the canvas failed. */
|
||||||
surfaceView.unlockCanvasAndPost (canvas);
|
if (canvas == null)
|
||||||
damageRegion.setEmpty ();
|
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
|
public void
|
||||||
@ -241,4 +296,18 @@ else if (child.getVisibility () != GONE)
|
|||||||
super.onFocusChanged (gainFocus, direction,
|
super.onFocusChanged (gainFocus, direction,
|
||||||
previouslyFocusedRect);
|
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.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.InputDevice;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import android.os.Build;
|
||||||
|
|
||||||
/* This defines a window, which is a handle. Windows represent a
|
/* This defines a window, which is a handle. Windows represent a
|
||||||
rectangular subset of the screen with their own contents.
|
rectangular subset of the screen with their own contents.
|
||||||
@ -68,6 +73,10 @@ public class EmacsWindow extends EmacsHandleObject
|
|||||||
window background. */
|
window background. */
|
||||||
private EmacsGC scratchGC;
|
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
|
public
|
||||||
EmacsWindow (short handle, final EmacsWindow parent, int x, int y,
|
EmacsWindow (short handle, final EmacsWindow parent, int x, int y,
|
||||||
int width, int height)
|
int width, int height)
|
||||||
@ -212,6 +221,7 @@ public class EmacsWindow extends EmacsHandleObject
|
|||||||
public void
|
public void
|
||||||
run ()
|
run ()
|
||||||
{
|
{
|
||||||
|
view.mustReportLayout = true;
|
||||||
view.requestLayout ();
|
view.requestLayout ();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -224,6 +234,8 @@ public class EmacsWindow extends EmacsHandleObject
|
|||||||
{
|
{
|
||||||
rect.right = rect.left + width;
|
rect.right = rect.left + width;
|
||||||
rect.bottom = rect.top + height;
|
rect.bottom = rect.top + height;
|
||||||
|
|
||||||
|
requestViewLayout ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,17 +291,7 @@ public class EmacsWindow extends EmacsHandleObject
|
|||||||
public Canvas
|
public Canvas
|
||||||
lockCanvas ()
|
lockCanvas ()
|
||||||
{
|
{
|
||||||
if (view.canvas != null)
|
return view.getCanvas ();
|
||||||
return view.canvas;
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void
|
|
||||||
unlockCanvas ()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -302,17 +304,7 @@ public class EmacsWindow extends EmacsHandleObject
|
|||||||
public void
|
public void
|
||||||
swapBuffers ()
|
swapBuffers ()
|
||||||
{
|
{
|
||||||
/* Before calling swapBuffers, make sure to flush the paint
|
view.swapBuffers ();
|
||||||
queue. */
|
|
||||||
EmacsService.SERVICE.flushPaintQueue ();
|
|
||||||
view.post (new Runnable () {
|
|
||||||
@Override
|
|
||||||
public void
|
|
||||||
run ()
|
|
||||||
{
|
|
||||||
view.swapBuffers ();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void
|
public void
|
||||||
@ -337,7 +329,7 @@ public class EmacsWindow extends EmacsHandleObject
|
|||||||
public Bitmap
|
public Bitmap
|
||||||
getBitmap ()
|
getBitmap ()
|
||||||
{
|
{
|
||||||
return view.bitmap;
|
return view.getBitmap ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void
|
public void
|
||||||
@ -357,6 +349,7 @@ public class EmacsWindow extends EmacsHandleObject
|
|||||||
recognized as an ASCII key press
|
recognized as an ASCII key press
|
||||||
event. */
|
event. */
|
||||||
event.getUnicodeChar (state));
|
event.getUnicodeChar (state));
|
||||||
|
lastModifiers = event.getModifiers ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void
|
public void
|
||||||
@ -372,6 +365,7 @@ public class EmacsWindow extends EmacsHandleObject
|
|||||||
event.getModifiers (),
|
event.getModifiers (),
|
||||||
keyCode,
|
keyCode,
|
||||||
event.getUnicodeChar (state));
|
event.getUnicodeChar (state));
|
||||||
|
lastModifiers = event.getModifiers ();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void
|
public void
|
||||||
@ -386,4 +380,105 @@ public class EmacsWindow extends EmacsHandleObject
|
|||||||
/* Destroy the associated frame when the activity is detached. */
|
/* Destroy the associated frame when the activity is detached. */
|
||||||
EmacsNative.sendWindowAction (this.handle, 0);
|
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