diff options
| author | Po Lu | 2024-04-23 14:30:38 +0800 |
|---|---|---|
| committer | Po Lu | 2024-04-23 14:30:38 +0800 |
| commit | b9c191d690fd5d1480858469df23cc4509996fae (patch) | |
| tree | 2e0536607f1442a99e88e39af8d24c51bab45aeb /java | |
| parent | 63765a74f15ef22109750414ec3025c8a40039f0 (diff) | |
| download | emacs-b9c191d690fd5d1480858469df23cc4509996fae.tar.gz emacs-b9c191d690fd5d1480858469df23cc4509996fae.zip | |
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.
Diffstat (limited to 'java')
| -rw-r--r-- | java/Makefile.in | 9 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsFillRectangle.java | 15 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsGC.java | 94 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsService.java | 7 |
4 files changed, 110 insertions, 15 deletions
diff --git a/java/Makefile.in b/java/Makefile.in index abddae6b5cf..35d2637837c 100644 --- a/java/Makefile.in +++ b/java/Makefile.in | |||
| @@ -197,10 +197,13 @@ install_temp: $(CROSS_BINS) $(CROSS_LIBS) $(RESOURCE_FILES) | |||
| 197 | $(AM_V_SILENT) mkdir -p install_temp/assets/etc | 197 | $(AM_V_SILENT) mkdir -p install_temp/assets/etc |
| 198 | $(AM_V_SILENT) mkdir -p install_temp/assets/lisp | 198 | $(AM_V_SILENT) mkdir -p install_temp/assets/lisp |
| 199 | $(AM_V_SILENT) mkdir -p install_temp/assets/info | 199 | $(AM_V_SILENT) mkdir -p install_temp/assets/info |
| 200 | # Install architecture independents to assets/etc and assets/lisp | 200 | $(AM_V_SILENT) mkdir -p install_temp/assets/bitmaps |
| 201 | # Install architecture independents to assets/etc, assets/lisp and | ||
| 202 | # assets/bitmaps | ||
| 201 | $(AM_V_SILENT) cp -r $(top_srcdir)/lisp install_temp/assets | 203 | $(AM_V_SILENT) cp -r $(top_srcdir)/lisp install_temp/assets |
| 202 | $(AM_V_SILENT) cp -r $(top_srcdir)/etc install_temp/assets | 204 | $(AM_V_SILENT) cp -r $(top_srcdir)/etc install_temp/assets |
| 203 | $(AM_V_SILENT) cp -r $(top_srcdir)/info install_temp/assets | 205 | $(AM_V_SILENT) cp -r $(top_srcdir)/info install_temp/assets |
| 206 | $(AM_V_SILENT) cp -r $(top_srcdir)/src/bitmaps install_temp/assets | ||
| 204 | # Replace etc/DOC generated by compiling Emacs for the build machine | 207 | # Replace etc/DOC generated by compiling Emacs for the build machine |
| 205 | # with etc/DOC from the cross-compiled Emacs. | 208 | # with etc/DOC from the cross-compiled Emacs. |
| 206 | $(AM_V_SILENT) test -f $(top_builddir)/cross/etc/DOC \ | 209 | $(AM_V_SILENT) test -f $(top_builddir)/cross/etc/DOC \ |
| @@ -354,8 +357,8 @@ public static final String[] EMACS_SHARED_LIBRARIES\ | |||
| 354 | 357 | ||
| 355 | # cf-stamp-1 is a phony target invoked in a second `make' instance after | 358 | # cf-stamp-1 is a phony target invoked in a second `make' instance after |
| 356 | # all shared libraries are compiled, because the computation of | 359 | # all shared libraries are compiled, because the computation of |
| 357 | # ALL_DEPENDENCIES cannot be postponed until that stage in this instance | 360 | # ALL_DEPENDENCIES in this instance of Make cannot be postponed until |
| 358 | # of Make. | 361 | # that stage. |
| 359 | cf-stamp: $(NDK_BUILD_SHARED) $(CROSS_LIBS) | 362 | cf-stamp: $(NDK_BUILD_SHARED) $(CROSS_LIBS) |
| 360 | $(AM_V_EMACSCONFIG) $(MAKE) cf-stamp-1 | 363 | $(AM_V_EMACSCONFIG) $(MAKE) cf-stamp-1 |
| 361 | $(AM_V_at) touch $@ | 364 | $(AM_V_at) touch $@ |
diff --git a/java/org/gnu/emacs/EmacsFillRectangle.java b/java/org/gnu/emacs/EmacsFillRectangle.java index ca87c06c014..f338a54f97b 100644 --- a/java/org/gnu/emacs/EmacsFillRectangle.java +++ b/java/org/gnu/emacs/EmacsFillRectangle.java | |||
| @@ -40,22 +40,23 @@ public final class EmacsFillRectangle | |||
| 40 | Canvas canvas; | 40 | Canvas canvas; |
| 41 | Bitmap clipBitmap; | 41 | Bitmap clipBitmap; |
| 42 | 42 | ||
| 43 | /* TODO implement stippling. */ | ||
| 44 | if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED) | ||
| 45 | return; | ||
| 46 | |||
| 47 | canvas = drawable.lockCanvas (gc); | 43 | canvas = drawable.lockCanvas (gc); |
| 48 | 44 | ||
| 49 | if (canvas == null) | 45 | if (canvas == null) |
| 50 | return; | 46 | return; |
| 51 | 47 | ||
| 52 | paint = gc.gcPaint; | ||
| 53 | rect = new Rect (x, y, x + width, y + height); | 48 | rect = new Rect (x, y, x + width, y + height); |
| 54 | 49 | ||
| 50 | paint = gc.gcPaint; | ||
| 55 | paint.setStyle (Paint.Style.FILL); | 51 | paint.setStyle (Paint.Style.FILL); |
| 56 | 52 | ||
| 57 | if (gc.clip_mask == null) | 53 | if (gc.clip_mask == null) |
| 58 | canvas.drawRect (rect, paint); | 54 | { |
| 55 | if (gc.fill_style != EmacsGC.GC_FILL_OPAQUE_STIPPLED) | ||
| 56 | canvas.drawRect (rect, paint); | ||
| 57 | else | ||
| 58 | gc.blitOpaqueStipple (canvas, rect); | ||
| 59 | } | ||
| 59 | else | 60 | else |
| 60 | { | 61 | { |
| 61 | /* Drawing with a clip mask involves calculating the | 62 | /* Drawing with a clip mask involves calculating the |
| @@ -113,4 +114,4 @@ public final class EmacsFillRectangle | |||
| 113 | 114 | ||
| 114 | drawable.damageRect (rect); | 115 | drawable.damageRect (rect); |
| 115 | } | 116 | } |
| 116 | } | 117 | }; |
diff --git a/java/org/gnu/emacs/EmacsGC.java b/java/org/gnu/emacs/EmacsGC.java index e45f0666fe2..96df0c61ca6 100644 --- a/java/org/gnu/emacs/EmacsGC.java +++ b/java/org/gnu/emacs/EmacsGC.java | |||
| @@ -22,10 +22,19 @@ package org.gnu.emacs; | |||
| 22 | import android.graphics.Rect; | 22 | import android.graphics.Rect; |
| 23 | import android.graphics.Paint; | 23 | import android.graphics.Paint; |
| 24 | 24 | ||
| 25 | import android.graphics.Bitmap; | ||
| 26 | import android.graphics.Canvas; | ||
| 27 | import android.graphics.ColorFilter; | ||
| 25 | import android.graphics.PorterDuff.Mode; | 28 | import android.graphics.PorterDuff.Mode; |
| 29 | import android.graphics.PorterDuffColorFilter; | ||
| 26 | import android.graphics.PorterDuffXfermode; | 30 | import android.graphics.PorterDuffXfermode; |
| 31 | import android.graphics.Shader.TileMode; | ||
| 27 | import android.graphics.Xfermode; | 32 | import android.graphics.Xfermode; |
| 28 | 33 | ||
| 34 | import android.graphics.drawable.BitmapDrawable; | ||
| 35 | |||
| 36 | import android.os.Build; | ||
| 37 | |||
| 29 | /* X like graphics context structures. Keep the enums in synch with | 38 | /* X like graphics context structures. Keep the enums in synch with |
| 30 | androidgui.h! */ | 39 | androidgui.h! */ |
| 31 | 40 | ||
| @@ -47,6 +56,9 @@ public final class EmacsGC extends EmacsHandleObject | |||
| 47 | public EmacsPixmap clip_mask, stipple; | 56 | public EmacsPixmap clip_mask, stipple; |
| 48 | public Paint gcPaint; | 57 | public Paint gcPaint; |
| 49 | 58 | ||
| 59 | /* Drawable object for rendering the stiple bitmap. */ | ||
| 60 | public BitmapDrawable tileObject; | ||
| 61 | |||
| 50 | /* ID incremented every time the clipping rectangles of any GC | 62 | /* ID incremented every time the clipping rectangles of any GC |
| 51 | changes. */ | 63 | changes. */ |
| 52 | private static long clip_serial; | 64 | private static long clip_serial; |
| @@ -86,6 +98,7 @@ public final class EmacsGC extends EmacsHandleObject | |||
| 86 | markDirty (boolean clipRectsChanged) | 98 | markDirty (boolean clipRectsChanged) |
| 87 | { | 99 | { |
| 88 | int i; | 100 | int i; |
| 101 | Bitmap stippleBitmap; | ||
| 89 | 102 | ||
| 90 | if (clipRectsChanged) | 103 | if (clipRectsChanged) |
| 91 | { | 104 | { |
| @@ -110,12 +123,85 @@ public final class EmacsGC extends EmacsHandleObject | |||
| 110 | gcPaint.setColor (foreground | 0xff000000); | 123 | gcPaint.setColor (foreground | 0xff000000); |
| 111 | gcPaint.setXfermode (function == GC_XOR | 124 | gcPaint.setXfermode (function == GC_XOR |
| 112 | ? xorAlu : srcInAlu); | 125 | ? xorAlu : srcInAlu); |
| 126 | |||
| 127 | /* Update the stipple object with the new stipple bitmap, or delete | ||
| 128 | it if the stipple has been cleared on systems too old to support | ||
| 129 | modifying such objects. */ | ||
| 130 | |||
| 131 | if (stipple != null) | ||
| 132 | { | ||
| 133 | stippleBitmap = stipple.getBitmap (); | ||
| 134 | |||
| 135 | /* Allocate a new tile object if none is already present or it | ||
| 136 | cannot be reconfigured. */ | ||
| 137 | if ((tileObject == null) | ||
| 138 | || (Build.VERSION.SDK_INT < Build.VERSION_CODES.S)) | ||
| 139 | { | ||
| 140 | tileObject = new BitmapDrawable (EmacsService.resources, | ||
| 141 | stippleBitmap); | ||
| 142 | tileObject.setTileModeXY (TileMode.MIRROR, TileMode.MIRROR); | ||
| 143 | } | ||
| 144 | else | ||
| 145 | /* Otherwise, update the existing tile object with the new | ||
| 146 | bitmap. */ | ||
| 147 | tileObject.setBitmap (stippleBitmap); | ||
| 148 | } | ||
| 149 | else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S | ||
| 150 | && tileObject != null) | ||
| 151 | tileObject.setBitmap (null); | ||
| 152 | else if (tileObject != null) | ||
| 153 | tileObject = null; | ||
| 113 | } | 154 | } |
| 114 | 155 | ||
| 115 | public void | 156 | /* Prepare the tile object to draw a stippled image onto a section of |
| 116 | resetXfermode () | 157 | a drawable defined by RECT. It is an error to call this function |
| 158 | unless the `stipple' field of the GContext is set. */ | ||
| 159 | |||
| 160 | private void | ||
| 161 | prepareStipple (Rect rect) | ||
| 117 | { | 162 | { |
| 118 | gcPaint.setXfermode (function == GC_XOR | 163 | int sx, sy; /* Stipple origin. */ |
| 119 | ? xorAlu : srcInAlu); | 164 | int bw, bh; /* Stipple size. */ |
| 165 | Bitmap bitmap; | ||
| 166 | Rect boundsRect; | ||
| 167 | |||
| 168 | /* Retrieve the dimensions of the stipple bitmap, which doubles as | ||
| 169 | the unit of advance for this stipple. */ | ||
| 170 | bitmap = tileObject.getBitmap (); | ||
| 171 | bw = bitmap.getWidth (); | ||
| 172 | bh = bitmap.getHeight (); | ||
| 173 | |||
| 174 | /* Align the lower left corner of the bounds rectangle to the | ||
| 175 | initial position of the stipple. */ | ||
| 176 | sx = (rect.left % bw) * -1 + (-ts_origin_x % bw) * -1; | ||
| 177 | sy = (rect.top % bh) * -1 + (-ts_origin_y % bh) * -1; | ||
| 178 | boundsRect = new Rect (rect.left + sx, rect.top + sy, | ||
| 179 | rect.right, rect.bottom); | ||
| 180 | tileObject.setBounds (boundsRect); | ||
| 181 | } | ||
| 182 | |||
| 183 | /* Fill the rectangle BOUNDS in the provided CANVAS with the stipple | ||
| 184 | pattern defined for this GContext, in the foreground color where | ||
| 185 | the pattern is on, and in the background color where off. */ | ||
| 186 | |||
| 187 | protected void | ||
| 188 | blitOpaqueStipple (Canvas canvas, Rect rect) | ||
| 189 | { | ||
| 190 | ColorFilter filter; | ||
| 191 | |||
| 192 | prepareStipple (rect); | ||
| 193 | filter = new PorterDuffColorFilter (foreground | 0xff000000, | ||
| 194 | Mode.SRC_IN); | ||
| 195 | tileObject.setColorFilter (filter); | ||
| 196 | |||
| 197 | canvas.save (); | ||
| 198 | canvas.clipRect (rect); | ||
| 199 | |||
| 200 | tileObject.draw (canvas); | ||
| 201 | filter = new PorterDuffColorFilter (background | 0xff000000, | ||
| 202 | Mode.SRC_OUT); | ||
| 203 | tileObject.setColorFilter (filter); | ||
| 204 | tileObject.draw (canvas); | ||
| 205 | canvas.restore (); | ||
| 120 | } | 206 | } |
| 121 | }; | 207 | }; |
diff --git a/java/org/gnu/emacs/EmacsService.java b/java/org/gnu/emacs/EmacsService.java index 2d4079c11b0..8e459ce4cdc 100644 --- a/java/org/gnu/emacs/EmacsService.java +++ b/java/org/gnu/emacs/EmacsService.java | |||
| @@ -64,6 +64,7 @@ import android.content.pm.PackageManager; | |||
| 64 | 64 | ||
| 65 | import android.content.res.AssetManager; | 65 | import android.content.res.AssetManager; |
| 66 | import android.content.res.Configuration; | 66 | import android.content.res.Configuration; |
| 67 | import android.content.res.Resources; | ||
| 67 | 68 | ||
| 68 | import android.hardware.input.InputManager; | 69 | import android.hardware.input.InputManager; |
| 69 | 70 | ||
| @@ -146,6 +147,9 @@ public final class EmacsService extends Service | |||
| 146 | thread. */ | 147 | thread. */ |
| 147 | private Thread mainThread; | 148 | private Thread mainThread; |
| 148 | 149 | ||
| 150 | /* "Resources" object required by GContext bookkeeping. */ | ||
| 151 | public static Resources resources; | ||
| 152 | |||
| 149 | static | 153 | static |
| 150 | { | 154 | { |
| 151 | servicingQuery = new AtomicInteger (); | 155 | servicingQuery = new AtomicInteger (); |
| @@ -238,10 +242,11 @@ public final class EmacsService extends Service | |||
| 238 | super.onCreate (); | 242 | super.onCreate (); |
| 239 | 243 | ||
| 240 | SERVICE = this; | 244 | SERVICE = this; |
| 245 | resources = getResources (); | ||
| 241 | handler = new Handler (Looper.getMainLooper ()); | 246 | handler = new Handler (Looper.getMainLooper ()); |
| 242 | manager = getAssets (); | 247 | manager = getAssets (); |
| 243 | app_context = getApplicationContext (); | 248 | app_context = getApplicationContext (); |
| 244 | metrics = getResources ().getDisplayMetrics (); | 249 | metrics = resources.getDisplayMetrics (); |
| 245 | pixelDensityX = metrics.xdpi; | 250 | pixelDensityX = metrics.xdpi; |
| 246 | pixelDensityY = metrics.ydpi; | 251 | pixelDensityY = metrics.ydpi; |
| 247 | tempScaledDensity = ((getScaledDensity (metrics) | 252 | tempScaledDensity = ((getScaledDensity (metrics) |