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)
{
rect.bottom -= bottom;
}
- @Override
- public EmacsGC
- getGC ()
- {
- return immutableGC;
- }
-
- @Override
- public void
- paintTo (Canvas canvas, Paint paint, EmacsGC immutableGC)
+ 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)
{
- 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. */
if (src_y + height > srcBitmap.getHeight ())
height = srcBitmap.getHeight () - src_y;
- rect = getRect ();
-
- if (alu == EmacsGC.GC_COPY)
- paint.setXfermode (null);
- else
- paint.setXfermode (xorAlu);
+ rect = new Rect (dest_x, dest_y, dest_x + width,
+ dest_y + height);
- if (immutableGC.clip_mask == null)
+ if (gc.clip_mask == null)
{
bitmap = Bitmap.createBitmap (srcBitmap,
src_x, src_y, width,
/* 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
/* 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 (),
/* Finally, draw the mask bitmap to the destination. */
paint.setXfermode (overAlu);
canvas.drawBitmap (maskBitmap, null, maskRect, paint);
+ gc.resetXfermode ();
}
+
+ canvas.restore ();
+ destination.damageRect (rect);
}
}
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));
- }
-
- @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;
+ canvas = drawable.lockCanvas ();
- /* 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 ();
-
- paint.setStyle (Paint.Style.STROKE);
-
- if (alu == EmacsGC.GC_COPY)
- paint.setXfermode (null);
- else
- paint.setXfermode (xorAlu);
+ canvas.save ();
- if (immutableGC.clip_mask == null)
- {
- paint.setColor (immutableGC.foreground | 0xff000000);
- canvas.drawLine ((float) x, (float) y,
- (float) x2, (float) y2,
- paint);
- }
- else
+ if (gc.real_clip_rects != null)
{
- 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);
+ for (i = 0; i < gc.real_clip_rects.length; ++i)
+ canvas.clipRect (gc.real_clip_rects[i]);
}
- paint.setXfermode (null);
+ paint.setStyle (Paint.Style.STROKE);
+
+ if (gc.clip_mask == null)
+ canvas.drawLine ((float) x, (float) y,
+ (float) x2, (float) y2,
+ paint);
+
+ /* DrawLine with clip mask not implemented; it is not used by
+ Emacs. */
+ canvas.restore ();
+ drawable.damageRect (rect);
}
}
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);
}
}
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
-{
- private int x, y, width, height;
- private EmacsDrawable drawable;
- private EmacsGC immutableGC;
- private static Xfermode xorAlu, srcInAlu;
-
- static
- {
- 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;
- }
+import android.util.Log;
- @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)
+public class EmacsDrawRectangle
+{
+ public static void
+ perform (EmacsDrawable drawable, EmacsGC gc,
+ int x, int y, int width, int height)
{
- 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 = new Rect (x, y, x + width, y + height);
+ canvas = drawable.lockCanvas ();
- paint.setStyle (Paint.Style.STROKE);
- paint.setStrokeWidth (1);
+ if (canvas == null)
+ return;
- if (alu == EmacsGC.GC_COPY)
- paint.setXfermode (null);
- else
- paint.setXfermode (xorAlu);
+ canvas.save ();
- if (immutableGC.clip_mask == null)
+ if (gc.real_clip_rects != null)
{
- paint.setColor (immutableGC.foreground | 0xff000000);
- canvas.drawRect (rect, paint);
+ 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);
+
+ if (gc.clip_mask == null)
+ canvas.drawRect (rect, paint);
else
{
- maskPaint = new Paint ();
- maskBitmap
- = immutableGC.clip_mask.bitmap.copy (Bitmap.Config.ARGB_8888,
- true);
-
- if (maskBitmap == null)
+ /* 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 (!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));
}
}
public interface EmacsDrawable
{
public Canvas lockCanvas ();
- public void unlockCanvas ();
public void damageRect (Rect damageRect);
public Bitmap getBitmap ();
public boolean isDestroyed ();
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;
+ public static void
+ perform (EmacsDrawable drawable, EmacsGC gc, Point points[])
+ {
+ Canvas canvas;
+ Path path;
+ Paint paint;
+ Rect rect;
+ RectF rectF;
+ int i;
- private static Xfermode xorAlu, srcInAlu;
+ canvas = drawable.lockCanvas ();
- static
- {
- xorAlu = new PorterDuffXfermode (Mode.XOR);
- srcInAlu = new PorterDuffXfermode (Mode.SRC_IN);
- };
+ if (canvas == null)
+ return;
- public
- EmacsFillPolygon (EmacsDrawable drawable, Point points[],
- EmacsGC immutableGC)
- {
- int i;
+ paint = gc.gcPaint;
+
+ canvas.save ();
- this.drawable = drawable;
- this.immutableGC = immutableGC;
+ 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 ();
path.close ();
}
- }
-
- @Override
- public Rect
- getRect ()
- {
- RectF rect;
- rect = new RectF (0, 0, 0, 0);
- path.computeBounds (rect, true);
+ /* Compute the damage rectangle. */
+ rectF = new RectF (0, 0, 0, 0);
+ path.computeBounds (rectF, true);
- return new Rect ((int) Math.floor (rect.left),
- (int) Math.floor (rect.top),
- (int) Math.ceil (rect.right),
- (int) Math.ceil (rect.bottom));
- }
+ rect = new Rect ((int) Math.floor (rectF.left),
+ (int) Math.floor (rectF.top),
+ (int) Math.ceil (rectF.right),
+ (int) Math.ceil (rectF.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 ();
+ paint.setStyle (Paint.Style.FILL);
- if (alu == EmacsGC.GC_COPY)
- paint.setXfermode (null);
- else
- paint.setXfermode (xorAlu);
+ if (gc.clip_mask == null)
+ canvas.drawPath (path, paint);
- paint.setStyle (Paint.Style.FILL);
+ canvas.restore ();
+ drawable.damageRect (rect);
- 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 (maskBitmap == null)
- return;
-
- 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. */
}
}
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
- {
- 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 ()
+ public static void
+ perform (EmacsDrawable drawable, EmacsGC gc,
+ int x, int y, int width, int height)
{
- 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 ();
- paint.setStyle (Paint.Style.FILL);
+ if (canvas == null)
+ return;
- if (alu == EmacsGC.GC_COPY)
- paint.setXfermode (null);
- else
- paint.setXfermode (xorAlu);
+ canvas.save ();
- if (immutableGC.clip_mask == null)
+ if (gc.real_clip_rects != null)
{
- paint.setColor (immutableGC.foreground | 0xff000000);
- canvas.drawRect (rect, paint);
+ 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 (gc.clip_mask == null)
+ canvas.drawRect (rect, paint);
else
{
- maskPaint = new Paint ();
- maskBitmap
- = immutableGC.clip_mask.bitmap.copy (Bitmap.Config.ARGB_8888,
- true);
-
- if (maskBitmap == null)
+ /* 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 (!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);
}
}
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 ();
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! */
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. */
fill_style = GC_FILL_SOLID;
function = GC_COPY;
foreground = 0;
- background = 0xffffffff;
+ background = 0xffffff;
+ gcPaint = new Paint ();
}
- public
- EmacsGC (EmacsGC source)
- {
- super ((short) 0);
+ /* Mark this GC as dirty. Apply parameters to the paint and
+ recompute real_clip_rects. */
+ public void
+ markDirty ()
+ {
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];
+ real_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);
+ 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;
- /* Mark this GC as dirty. This means immutableGC will return a new
- copy of this GC the next time it is called. */
+ gcPaint.setColor (foreground | 0xff000000);
+ gcPaint.setXfermode (function == GC_XOR
+ ? xorAlu : srcInAlu);
+ }
public void
- markDirty ()
+ resetXfermode ()
{
- dirty = true;
+ gcPaint.setXfermode (function == GC_XOR
+ ? xorAlu : srcInAlu);
}
-
- public EmacsGC
- immutableGC ()
- {
- if (immutableGC == null || dirty)
- {
- immutableGC = new EmacsGC (this);
- dirty = false;
- }
-
- return immutableGC;
- };
};
/* 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");
break;
}
+ bitmap.eraseColor (0xff000000);
+
this.width = width;
this.height = height;
this.depth = depth;
return canvas;
}
- @Override
- public void
- unlockCanvas ()
- {
-
- }
-
@Override
public void
damageRect (Rect damageRect)
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)
}
};
- 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;
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.
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
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;
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];
backgroundRect.right = x + backgroundWidth;
backgroundRect.bottom = y + sdk7FontObject.descent;
- op = new Sdk7DrawString (sdk7FontObject, charsArray,
- gc.immutableGC (), drawable,
- withBackground,
- backgroundRect, x, y);
+ canvas = drawable.lockCanvas ();
+
+ 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);
+ }
- EmacsService.SERVICE.appendPaintOperation (op);
+ 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;
}
};
package org.gnu.emacs;
-import java.lang.Runnable;
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
private EmacsThread thread;
private Handler handler;
- private EmacsPaintQueue paintQueue;
/* Display metrics used by font backends. */
public DisplayMetrics metrics;
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. */
-
-\f
-
- 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
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
{
window.clearArea (x, y, width, height);
}
-
- public void
- appendPaintOperation (EmacsPaintReq op)
- {
- ensurePaintQueue ();
- paintQueue.appendPaintOperation (op);
- checkFlush ();
- }
};
public class EmacsSurfaceView extends SurfaceView
{
+ public Object surfaceChangeLock;
private boolean created;
public
{
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;
+ }
}
});
}
import android.view.View;
import android.view.KeyEvent;
+import android.view.MotionEvent;
import android.view.ViewGroup;
import android.graphics.Bitmap;
/* 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)
{
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)
}
@Override
- protected void
+ protected synchronized void
onLayout (boolean changed, int left, int top, int right,
int bottom)
{
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)
}
}
- 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. */
+
+ synchronized (surfaceView.surfaceChangeLock)
+ {
+ damageRect = damageRegion.getBounds ();
- /* Lock the canvas with the specified damage. */
- damageRect = damageRegion.getBounds ();
- canvas = surfaceView.lockCanvas (damageRect);
+ if (!surfaceView.isCreated ())
+ return;
- /* Return if locking the canvas failed. */
- if (canvas == null)
- return;
+ if (bitmap == null)
+ return;
+
+ /* Lock the canvas with the specified damage. */
+ canvas = surfaceView.lockCanvas (damageRect);
- /* Copy from the back buffer to the canvas. If damageRect was
- made empty, then draw the entire back buffer. */
+ /* Return if locking the canvas failed. */
+ if (canvas == null)
+ return;
- if (damageRect.isEmpty ())
- canvas.drawBitmap (bitmap, 0f, 0f, paint);
- else
- canvas.drawBitmap (bitmap, damageRect, damageRect, paint);
+ /* Copy from the back buffer to the canvas. If damageRect was
+ made empty, then draw the entire back buffer. */
- /* Unlock the canvas and clear the damage. */
- surfaceView.unlockCanvasAndPost (canvas);
- damageRegion.setEmpty ();
+ 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
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);
+ }
};
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.
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)
public void
run ()
{
+ view.mustReportLayout = true;
view.requestLayout ();
}
});
{
rect.right = rect.left + width;
rect.bottom = rect.top + height;
+
+ requestViewLayout ();
}
}
public Canvas
lockCanvas ()
{
- if (view.canvas != null)
- return view.canvas;
-
- return null;
- }
-
- @Override
- public void
- unlockCanvas ()
- {
-
+ return view.getCanvas ();
}
@Override
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
public Bitmap
getBitmap ()
{
- return view.bitmap;
+ return view.getBitmap ();
}
public void
recognized as an ASCII key press
event. */
event.getUnicodeChar (state));
+ lastModifiers = event.getModifiers ();
}
public void
event.getModifiers (),
keyCode,
event.getUnicodeChar (state));
+ lastModifiers = event.getModifiers ();
}
public void
/* 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;
+ }
};