mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-21 06:55:39 +00:00
Implement face stipples on Android
* .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.
This commit is contained in:
parent
63765a74f1
commit
b9c191d690
2
.gitignore
vendored
2
.gitignore
vendored
@ -68,7 +68,7 @@ java/org/gnu/emacs/R.java
|
||||
|
||||
# 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
|
||||
|
@ -197,10 +197,13 @@ install_temp: $(CROSS_BINS) $(CROSS_LIBS) $(RESOURCE_FILES)
|
||||
$(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 \
|
||||
@ -354,8 +357,8 @@ public static final String[] EMACS_SHARED_LIBRARIES\
|
||||
|
||||
# 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 $@
|
||||
|
@ -40,22 +40,23 @@ public final class EmacsFillRectangle
|
||||
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
|
||||
@ -113,4 +114,4 @@ maskRect, new Rect (0, 0,
|
||||
|
||||
drawable.damageRect (rect);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -22,10 +22,19 @@
|
||||
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! */
|
||||
|
||||
@ -47,6 +56,9 @@ public final class EmacsGC extends EmacsHandleObject
|
||||
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;
|
||||
@ -86,6 +98,7 @@ public final class EmacsGC extends EmacsHandleObject
|
||||
markDirty (boolean clipRectsChanged)
|
||||
{
|
||||
int i;
|
||||
Bitmap stippleBitmap;
|
||||
|
||||
if (clipRectsChanged)
|
||||
{
|
||||
@ -110,12 +123,85 @@ public final class EmacsGC extends EmacsHandleObject
|
||||
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 ();
|
||||
}
|
||||
};
|
||||
|
@ -64,6 +64,7 @@
|
||||
|
||||
import android.content.res.AssetManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
|
||||
import android.hardware.input.InputManager;
|
||||
|
||||
@ -146,6 +147,9 @@ public final class EmacsService extends Service
|
||||
thread. */
|
||||
private Thread mainThread;
|
||||
|
||||
/* "Resources" object required by GContext bookkeeping. */
|
||||
public static Resources resources;
|
||||
|
||||
static
|
||||
{
|
||||
servicingQuery = new AtomicInteger ();
|
||||
@ -238,10 +242,11 @@ public final class EmacsService extends Service
|
||||
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)
|
||||
|
@ -4882,8 +4882,8 @@ android_pixmap
|
||||
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 *
|
||||
@ -5994,40 +5994,22 @@ android_toggle_on_screen_keyboard (android_window window, bool show)
|
||||
|
||||
|
||||
|
||||
#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 ();
|
||||
}
|
||||
|
@ -69,12 +69,6 @@ typedef struct
|
||||
unsigned width, height;
|
||||
} Emacs_Rectangle;
|
||||
|
||||
#else
|
||||
|
||||
typedef struct android_rectangle Emacs_Rectangle;
|
||||
|
||||
#endif
|
||||
|
||||
/* XGCValues-like struct used by non-X GUI code. */
|
||||
typedef struct
|
||||
{
|
||||
@ -88,6 +82,19 @@ 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
|
||||
|
@ -95,7 +95,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
# 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;
|
||||
|
@ -419,7 +419,7 @@ x_bitmap_stipple (struct frame *f, Pixmap pixmap)
|
||||
#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)
|
||||
{
|
||||
|
@ -503,6 +503,10 @@ sfntfont_android_put_glyphs (struct glyph_string *s, int from,
|
||||
|
||||
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. */
|
||||
|
24
src/xfaces.c
24
src/xfaces.c
@ -619,21 +619,7 @@ static struct android_gc *
|
||||
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
|
||||
@ -4630,14 +4616,18 @@ prepare_face_for_display (struct frame *f, struct face *face)
|
||||
#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);
|
||||
|
Loading…
Reference in New Issue
Block a user