* .gitignore:
* java/Makefile.in: Fix typos.
* java/org/gnu/emacs/EmacsFillRectangle.java (perform): Call
blitOpaqueStipple if filling an unobscured rectangle with an
opaque stipple.
* java/org/gnu/emacs/EmacsGC.java (EmacsGC) <tileObject>: New
field.
(markDirty): Synchronize the current stipple with tileObject.
(prepareStipple, blitOpaqueStipple): New functions.
* java/org/gnu/emacs/EmacsService.java (EmacsService)
<resources>: New static field.
(onCreate): Set it.
* src/android.c (android_create_bitmap_from_data): Correct order
of arguments to android_create_pixmap_from_bitmap_data.
(HAS_BUILTIN_TRAP): Delete macro.
(emacs_abort): Always induce backtraces by means of a NULL
pointer deference.
* src/dispextern.h (Emacs_GC, Emacs_Rectangle, GCForeground)
(GCBackground, GCFillStyle, GCStipple, FillOpaqueStipple)
[HAVE_ANDROID]: Define to their Android counterparts rather
than simulating their existence.
* src/epaths.in: Set bitmap path to /assets/bitmaps on Android.
* src/image.c (image_bitmap_pixmap): Also enable when
HAVE_ANDROID.
* src/sfntfont-android.c (sfntfont_android_put_glyphs): Assert
that this is never called to draw a stippled background.
* src/xfaces.c (x_create_gc) [HAVE_ANDROID]: Redefine as
wrapper around android_create_gc.
(prepare_face_for_display) [HAVE_ANDROID]: Enable stipples.
(cherry picked from commit
b9c191d690fd5d1480858469df23cc4509996fae)
# Built by `make'.
java/org/gnu/emacs/EmacsConfig.java
-java/org/gnu/emacs/cf-stamp
+java/cf-stamp
# Built by `config.status'.
java/AndroidManifest.xml
$(AM_V_SILENT) mkdir -p install_temp/assets/etc
$(AM_V_SILENT) mkdir -p install_temp/assets/lisp
$(AM_V_SILENT) mkdir -p install_temp/assets/info
-# Install architecture independents to assets/etc and assets/lisp
+ $(AM_V_SILENT) mkdir -p install_temp/assets/bitmaps
+# Install architecture independents to assets/etc, assets/lisp and
+# assets/bitmaps
$(AM_V_SILENT) cp -r $(top_srcdir)/lisp install_temp/assets
$(AM_V_SILENT) cp -r $(top_srcdir)/etc install_temp/assets
$(AM_V_SILENT) cp -r $(top_srcdir)/info install_temp/assets
+ $(AM_V_SILENT) cp -r $(top_srcdir)/src/bitmaps install_temp/assets
# Replace etc/DOC generated by compiling Emacs for the build machine
# with etc/DOC from the cross-compiled Emacs.
$(AM_V_SILENT) test -f $(top_builddir)/cross/etc/DOC \
# cf-stamp-1 is a phony target invoked in a second `make' instance after
# all shared libraries are compiled, because the computation of
-# ALL_DEPENDENCIES cannot be postponed until that stage in this instance
-# of Make.
+# ALL_DEPENDENCIES in this instance of Make cannot be postponed until
+# that stage.
cf-stamp: $(NDK_BUILD_SHARED) $(CROSS_LIBS)
$(AM_V_EMACSCONFIG) $(MAKE) cf-stamp-1
$(AM_V_at) touch $@
Canvas canvas;
Bitmap clipBitmap;
- /* TODO implement stippling. */
- if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
- return;
-
canvas = drawable.lockCanvas (gc);
if (canvas == null)
return;
- paint = gc.gcPaint;
rect = new Rect (x, y, x + width, y + height);
+ paint = gc.gcPaint;
paint.setStyle (Paint.Style.FILL);
if (gc.clip_mask == null)
- canvas.drawRect (rect, paint);
+ {
+ if (gc.fill_style != EmacsGC.GC_FILL_OPAQUE_STIPPLED)
+ canvas.drawRect (rect, paint);
+ else
+ gc.blitOpaqueStipple (canvas, rect);
+ }
else
{
/* Drawing with a clip mask involves calculating the
drawable.damageRect (rect);
}
-}
+};
import android.graphics.Rect;
import android.graphics.Paint;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
import android.graphics.PorterDuff.Mode;
+import android.graphics.PorterDuffColorFilter;
import android.graphics.PorterDuffXfermode;
+import android.graphics.Shader.TileMode;
import android.graphics.Xfermode;
+import android.graphics.drawable.BitmapDrawable;
+
+import android.os.Build;
+
/* X like graphics context structures. Keep the enums in synch with
androidgui.h! */
public EmacsPixmap clip_mask, stipple;
public Paint gcPaint;
+ /* Drawable object for rendering the stiple bitmap. */
+ public BitmapDrawable tileObject;
+
/* ID incremented every time the clipping rectangles of any GC
changes. */
private static long clip_serial;
markDirty (boolean clipRectsChanged)
{
int i;
+ Bitmap stippleBitmap;
if (clipRectsChanged)
{
gcPaint.setColor (foreground | 0xff000000);
gcPaint.setXfermode (function == GC_XOR
? xorAlu : srcInAlu);
+
+ /* Update the stipple object with the new stipple bitmap, or delete
+ it if the stipple has been cleared on systems too old to support
+ modifying such objects. */
+
+ if (stipple != null)
+ {
+ stippleBitmap = stipple.getBitmap ();
+
+ /* Allocate a new tile object if none is already present or it
+ cannot be reconfigured. */
+ if ((tileObject == null)
+ || (Build.VERSION.SDK_INT < Build.VERSION_CODES.S))
+ {
+ tileObject = new BitmapDrawable (EmacsService.resources,
+ stippleBitmap);
+ tileObject.setTileModeXY (TileMode.MIRROR, TileMode.MIRROR);
+ }
+ else
+ /* Otherwise, update the existing tile object with the new
+ bitmap. */
+ tileObject.setBitmap (stippleBitmap);
+ }
+ else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
+ && tileObject != null)
+ tileObject.setBitmap (null);
+ else if (tileObject != null)
+ tileObject = null;
}
- public void
- resetXfermode ()
+ /* Prepare the tile object to draw a stippled image onto a section of
+ a drawable defined by RECT. It is an error to call this function
+ unless the `stipple' field of the GContext is set. */
+
+ private void
+ prepareStipple (Rect rect)
{
- gcPaint.setXfermode (function == GC_XOR
- ? xorAlu : srcInAlu);
+ int sx, sy; /* Stipple origin. */
+ int bw, bh; /* Stipple size. */
+ Bitmap bitmap;
+ Rect boundsRect;
+
+ /* Retrieve the dimensions of the stipple bitmap, which doubles as
+ the unit of advance for this stipple. */
+ bitmap = tileObject.getBitmap ();
+ bw = bitmap.getWidth ();
+ bh = bitmap.getHeight ();
+
+ /* Align the lower left corner of the bounds rectangle to the
+ initial position of the stipple. */
+ sx = (rect.left % bw) * -1 + (-ts_origin_x % bw) * -1;
+ sy = (rect.top % bh) * -1 + (-ts_origin_y % bh) * -1;
+ boundsRect = new Rect (rect.left + sx, rect.top + sy,
+ rect.right, rect.bottom);
+ tileObject.setBounds (boundsRect);
+ }
+
+ /* Fill the rectangle BOUNDS in the provided CANVAS with the stipple
+ pattern defined for this GContext, in the foreground color where
+ the pattern is on, and in the background color where off. */
+
+ protected void
+ blitOpaqueStipple (Canvas canvas, Rect rect)
+ {
+ ColorFilter filter;
+
+ prepareStipple (rect);
+ filter = new PorterDuffColorFilter (foreground | 0xff000000,
+ Mode.SRC_IN);
+ tileObject.setColorFilter (filter);
+
+ canvas.save ();
+ canvas.clipRect (rect);
+
+ tileObject.draw (canvas);
+ filter = new PorterDuffColorFilter (background | 0xff000000,
+ Mode.SRC_OUT);
+ tileObject.setColorFilter (filter);
+ tileObject.draw (canvas);
+ canvas.restore ();
}
};
import android.content.res.AssetManager;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.hardware.input.InputManager;
thread. */
private Thread mainThread;
+ /* "Resources" object required by GContext bookkeeping. */
+ public static Resources resources;
+
static
{
servicingQuery = new AtomicInteger ();
super.onCreate ();
SERVICE = this;
+ resources = getResources ();
handler = new Handler (Looper.getMainLooper ());
manager = getAssets ();
app_context = getApplicationContext ();
- metrics = getResources ().getDisplayMetrics ();
+ metrics = resources.getDisplayMetrics ();
pixelDensityX = metrics.xdpi;
pixelDensityY = metrics.ydpi;
tempScaledDensity = ((getScaledDensity (metrics)
android_create_bitmap_from_data (char *bits, unsigned int width,
unsigned int height)
{
- return android_create_pixmap_from_bitmap_data (bits, 1, 0,
- width, height, 1);
+ return android_create_pixmap_from_bitmap_data (bits, width, height,
+ 1, 0, 1);
}
struct android_image *
\f
-#if defined __clang_major__ && __clang_major__ < 5
-# define HAS_BUILTIN_TRAP 0
-#elif 3 < __GNUC__ + (3 < __GNUC_MINOR__ + (4 <= __GNUC_PATCHLEVEL__))
-# define HAS_BUILTIN_TRAP 1
-#elif defined __has_builtin
-# define HAS_BUILTIN_TRAP __has_builtin (__builtin_trap)
-#else /* !__has_builtin */
-# define HAS_BUILTIN_TRAP 0
-#endif /* defined __clang_major__ && __clang_major__ < 5 */
-
/* emacs_abort implementation for Android. This logs a stack
trace. */
void
emacs_abort (void)
{
-#ifndef HAS_BUILTIN_TRAP
volatile char *foo;
-#endif /* !HAS_BUILTIN_TRAP */
__android_log_print (ANDROID_LOG_FATAL, __func__,
"emacs_abort called, please review the following"
" stack trace");
-#ifndef HAS_BUILTIN_TRAP
/* Induce a NULL pointer dereference to make debuggerd generate a
tombstone. */
foo = NULL;
*foo = '\0';
-#else /* HAS_BUILTIN_TRAP */
- /* Crash through __builtin_trap instead. This appears to more
- uniformly elicit crash reports from debuggerd. */
- __builtin_trap ();
-#endif /* !HAS_BUILTIN_TRAP */
abort ();
}
unsigned width, height;
} Emacs_Rectangle;
-#else
-
-typedef struct android_rectangle Emacs_Rectangle;
-
-#endif
-
/* XGCValues-like struct used by non-X GUI code. */
typedef struct
{
#define GCForeground 0x01
#define GCBackground 0x02
+#else
+
+typedef struct android_rectangle Emacs_Rectangle;
+typedef struct android_gc_values Emacs_GC;
+
+#define GCForeground ANDROID_GC_FOREGROUND
+#define GCBackground ANDROID_GC_BACKGROUND
+#define GCFillStyle ANDROID_GC_FILL_STYLE
+#define GCStipple ANDROID_GC_STIPPLE
+#define FillOpaqueStippled ANDROID_FILL_OPAQUE_STIPPLED
+
+#endif
+
#endif /* HAVE_X_WINDOWS */
#ifdef MSDOS
# define PATH_DOC "/assets/etc/"
# define PATH_INFO "/assets/info/"
# define PATH_GAME ""
- # define PATH_BITMAPS ""
+ # define PATH_BITMAPS "/assets/bitmaps/"
extern char *android_site_load_path;
extern char *android_lib_dir;
#endif /* USE_CAIRO */
#endif
-#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI)
+#if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) || defined (HAVE_ANDROID)
ptrdiff_t
image_bitmap_pixmap (struct frame *f, ptrdiff_t id)
{
if (with_background)
{
+ /* The background should have been filled in advance if a stipple
+ is enabled. */
+ eassert (s->gc->fill_style != ANDROID_FILL_OPAQUE_STIPPLED);
+
/* Fill the background. First, offset the background rectangle
to become relative from text_rectangle.x,
text_rectangle.y. */
x_create_gc (struct frame *f, unsigned long value_mask,
Emacs_GC *xgcv)
{
- struct android_gc_values gcv;
- unsigned long mask;
-
- gcv.foreground = xgcv->foreground;
- gcv.background = xgcv->background;
-
- mask = 0;
-
- if (value_mask & GCForeground)
- mask |= ANDROID_GC_FOREGROUND;
-
- if (value_mask & GCBackground)
- mask |= ANDROID_GC_BACKGROUND;
-
- return android_create_gc (mask, &gcv);
+ return android_create_gc (value_mask, xgcv);
}
static void
#endif
block_input ();
-#ifdef HAVE_X_WINDOWS
+#if defined HAVE_X_WINDOWS || defined HAVE_ANDROID
if (face->stipple)
{
egc.fill_style = FillOpaqueStippled;
+#ifndef ANDROID_STUBIFY
egc.stipple = image_bitmap_pixmap (f, face->stipple);
+#else /* !ANDROID_STUBIFY */
+ emacs_abort ();
+#endif /* !ANDROID_STUBIFY */
mask |= GCFillStyle | GCStipple;
}
-#endif
+#endif /* HAVE_X_WINDOWS || HAVE_ANDROID */
face->gc = x_create_gc (f, mask, &egc);
if (face->font)
font_prepare_for_face (f, face);