diff options
| author | Po Lu | 2023-01-08 15:39:02 +0800 |
|---|---|---|
| committer | Po Lu | 2023-01-08 15:39:02 +0800 |
| commit | 695e26079eb60d10ffe25bb8ae91ebc6131fb27d (patch) | |
| tree | bc18692c1e4c0f5aa3e6707850f4c2023bc75e81 /java | |
| parent | e816e570393a964383e8b42330f5582c4c0a54f2 (diff) | |
| download | emacs-695e26079eb60d10ffe25bb8ae91ebc6131fb27d.tar.gz emacs-695e26079eb60d10ffe25bb8ae91ebc6131fb27d.zip | |
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.
Diffstat (limited to 'java')
| -rw-r--r-- | java/org/gnu/emacs/EmacsCopyArea.java | 131 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsDrawLine.java | 120 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsDrawPoint.java | 11 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsDrawRectangle.java | 160 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsDrawable.java | 1 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsFillPolygon.java | 128 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsFillRectangle.java | 152 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsFontDriver.java | 2 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsGC.java | 77 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsNative.java | 22 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsPixmap.java | 9 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsSdk23FontDriver.java | 71 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsSdk7FontDriver.java | 139 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsService.java | 122 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsSurfaceView.java | 22 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsView.java | 133 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsWindow.java | 141 |
17 files changed, 685 insertions, 756 deletions
diff --git a/java/org/gnu/emacs/EmacsCopyArea.java b/java/org/gnu/emacs/EmacsCopyArea.java index 0dd5b2c1fb6..00e817bb97d 100644 --- a/java/org/gnu/emacs/EmacsCopyArea.java +++ b/java/org/gnu/emacs/EmacsCopyArea.java | |||
| @@ -27,54 +27,16 @@ import android.graphics.PorterDuffXfermode; | |||
| 27 | import android.graphics.Rect; | 27 | import android.graphics.Rect; |
| 28 | import android.graphics.Xfermode; | 28 | import android.graphics.Xfermode; |
| 29 | 29 | ||
| 30 | public class EmacsCopyArea implements EmacsPaintReq | 30 | public class EmacsCopyArea |
| 31 | { | 31 | { |
| 32 | private int src_x, src_y, dest_x, dest_y, width, height; | 32 | private static Xfermode overAlu; |
| 33 | private EmacsDrawable destination, source; | ||
| 34 | private EmacsGC immutableGC; | ||
| 35 | private static Xfermode xorAlu, srcInAlu, overAlu; | ||
| 36 | 33 | ||
| 37 | static | 34 | static |
| 38 | { | 35 | { |
| 39 | overAlu = new PorterDuffXfermode (Mode.SRC_OVER); | 36 | overAlu = new PorterDuffXfermode (Mode.SRC_OVER); |
| 40 | xorAlu = new PorterDuffXfermode (Mode.XOR); | ||
| 41 | srcInAlu = new PorterDuffXfermode (Mode.SRC_IN); | ||
| 42 | }; | 37 | }; |
| 43 | 38 | ||
| 44 | public | 39 | private static void |
| 45 | EmacsCopyArea (EmacsDrawable source, EmacsDrawable destination, | ||
| 46 | int src_x, int src_y, int width, int height, | ||
| 47 | int dest_x, int dest_y, EmacsGC immutableGC) | ||
| 48 | { | ||
| 49 | Bitmap bitmap; | ||
| 50 | |||
| 51 | this.destination = destination; | ||
| 52 | this.source = source; | ||
| 53 | this.src_x = src_x; | ||
| 54 | this.src_y = src_y; | ||
| 55 | this.width = width; | ||
| 56 | this.height = height; | ||
| 57 | this.dest_x = dest_x; | ||
| 58 | this.dest_y = dest_y; | ||
| 59 | this.immutableGC = immutableGC; | ||
| 60 | } | ||
| 61 | |||
| 62 | @Override | ||
| 63 | public Rect | ||
| 64 | getRect () | ||
| 65 | { | ||
| 66 | return new Rect (dest_x, dest_y, dest_x + width, | ||
| 67 | dest_y + height); | ||
| 68 | } | ||
| 69 | |||
| 70 | @Override | ||
| 71 | public EmacsDrawable | ||
| 72 | getDrawable () | ||
| 73 | { | ||
| 74 | return destination; | ||
| 75 | } | ||
| 76 | |||
| 77 | private void | ||
| 78 | insetRectBy (Rect rect, int left, int top, int right, | 40 | insetRectBy (Rect rect, int left, int top, int right, |
| 79 | int bottom) | 41 | int bottom) |
| 80 | { | 42 | { |
| @@ -84,30 +46,38 @@ public class EmacsCopyArea implements EmacsPaintReq | |||
| 84 | rect.bottom -= bottom; | 46 | rect.bottom -= bottom; |
| 85 | } | 47 | } |
| 86 | 48 | ||
| 87 | @Override | 49 | public static void |
| 88 | public EmacsGC | 50 | perform (EmacsDrawable source, EmacsGC gc, |
| 89 | getGC () | 51 | EmacsDrawable destination, |
| 90 | { | 52 | int src_x, int src_y, int width, int height, |
| 91 | return immutableGC; | 53 | int dest_x, int dest_y) |
| 92 | } | ||
| 93 | |||
| 94 | @Override | ||
| 95 | public void | ||
| 96 | paintTo (Canvas canvas, Paint paint, EmacsGC immutableGC) | ||
| 97 | { | 54 | { |
| 98 | int alu; | 55 | int i; |
| 99 | Bitmap bitmap; | 56 | Bitmap bitmap; |
| 100 | Paint maskPaint; | 57 | Paint maskPaint, paint; |
| 101 | Canvas maskCanvas; | 58 | Canvas maskCanvas, canvas; |
| 102 | Bitmap srcBitmap, maskBitmap, clipBitmap; | 59 | Bitmap srcBitmap, maskBitmap, clipBitmap; |
| 103 | Rect rect, maskRect, srcRect, dstRect, maskDestRect; | 60 | Rect rect, maskRect, srcRect, dstRect, maskDestRect; |
| 104 | boolean needFill; | 61 | boolean needFill; |
| 105 | 62 | ||
| 106 | /* TODO implement stippling. */ | 63 | /* TODO implement stippling. */ |
| 107 | if (immutableGC.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED) | 64 | if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED) |
| 108 | return; | 65 | return; |
| 109 | 66 | ||
| 110 | alu = immutableGC.function; | 67 | paint = gc.gcPaint; |
| 68 | |||
| 69 | canvas = destination.lockCanvas (); | ||
| 70 | |||
| 71 | if (canvas == null) | ||
| 72 | return; | ||
| 73 | |||
| 74 | canvas.save (); | ||
| 75 | |||
| 76 | if (gc.real_clip_rects != null) | ||
| 77 | { | ||
| 78 | for (i = 0; i < gc.real_clip_rects.length; ++i) | ||
| 79 | canvas.clipRect (gc.real_clip_rects[i]); | ||
| 80 | } | ||
| 111 | 81 | ||
| 112 | /* A copy must be created or drawBitmap could end up overwriting | 82 | /* A copy must be created or drawBitmap could end up overwriting |
| 113 | itself. */ | 83 | itself. */ |
| @@ -137,14 +107,10 @@ public class EmacsCopyArea implements EmacsPaintReq | |||
| 137 | if (src_y + height > srcBitmap.getHeight ()) | 107 | if (src_y + height > srcBitmap.getHeight ()) |
| 138 | height = srcBitmap.getHeight () - src_y; | 108 | height = srcBitmap.getHeight () - src_y; |
| 139 | 109 | ||
| 140 | rect = getRect (); | 110 | rect = new Rect (dest_x, dest_y, dest_x + width, |
| 141 | 111 | dest_y + height); | |
| 142 | if (alu == EmacsGC.GC_COPY) | ||
| 143 | paint.setXfermode (null); | ||
| 144 | else | ||
| 145 | paint.setXfermode (xorAlu); | ||
| 146 | 112 | ||
| 147 | if (immutableGC.clip_mask == null) | 113 | if (gc.clip_mask == null) |
| 148 | { | 114 | { |
| 149 | bitmap = Bitmap.createBitmap (srcBitmap, | 115 | bitmap = Bitmap.createBitmap (srcBitmap, |
| 150 | src_x, src_y, width, | 116 | src_x, src_y, width, |
| @@ -156,17 +122,17 @@ public class EmacsCopyArea implements EmacsPaintReq | |||
| 156 | /* Drawing with a clip mask involves calculating the | 122 | /* Drawing with a clip mask involves calculating the |
| 157 | intersection of the clip mask with the dst rect, and | 123 | intersection of the clip mask with the dst rect, and |
| 158 | extrapolating the corresponding part of the src rect. */ | 124 | extrapolating the corresponding part of the src rect. */ |
| 159 | clipBitmap = immutableGC.clip_mask.bitmap; | 125 | clipBitmap = gc.clip_mask.bitmap; |
| 160 | dstRect = new Rect (dest_x, dest_y, | 126 | dstRect = new Rect (dest_x, dest_y, |
| 161 | dest_x + width, | 127 | dest_x + width, |
| 162 | dest_y + height); | 128 | dest_y + height); |
| 163 | maskRect = new Rect (immutableGC.clip_x_origin, | 129 | maskRect = new Rect (gc.clip_x_origin, |
| 164 | immutableGC.clip_y_origin, | 130 | gc.clip_y_origin, |
| 165 | (immutableGC.clip_x_origin | 131 | (gc.clip_x_origin |
| 166 | + clipBitmap.getWidth ()), | 132 | + clipBitmap.getWidth ()), |
| 167 | (immutableGC.clip_y_origin | 133 | (gc.clip_y_origin |
| 168 | + clipBitmap.getHeight ())); | 134 | + clipBitmap.getHeight ())); |
| 169 | clipBitmap = immutableGC.clip_mask.bitmap; | 135 | clipBitmap = gc.clip_mask.bitmap; |
| 170 | 136 | ||
| 171 | if (!maskRect.setIntersect (dstRect, maskRect)) | 137 | if (!maskRect.setIntersect (dstRect, maskRect)) |
| 172 | /* There is no intersection between the clip mask and the | 138 | /* There is no intersection between the clip mask and the |
| @@ -191,20 +157,21 @@ public class EmacsCopyArea implements EmacsPaintReq | |||
| 191 | 157 | ||
| 192 | /* Draw the mask onto the maskBitmap. */ | 158 | /* Draw the mask onto the maskBitmap. */ |
| 193 | maskCanvas = new Canvas (maskBitmap); | 159 | maskCanvas = new Canvas (maskBitmap); |
| 194 | maskRect.offset (-immutableGC.clip_x_origin, | 160 | maskPaint = new Paint (); |
| 195 | -immutableGC.clip_y_origin); | 161 | maskRect.offset (-gc.clip_x_origin, |
| 196 | maskCanvas.drawBitmap (immutableGC.clip_mask.bitmap, | 162 | -gc.clip_y_origin); |
| 197 | maskRect, new Rect (0, 0, | 163 | maskCanvas.drawBitmap (gc.clip_mask.bitmap, |
| 198 | maskRect.width (), | 164 | maskRect, |
| 199 | maskRect.height ()), | 165 | new Rect (0, 0, |
| 200 | paint); | 166 | maskRect.width (), |
| 201 | maskRect.offset (immutableGC.clip_x_origin, | 167 | maskRect.height ()), |
| 202 | immutableGC.clip_y_origin); | 168 | maskPaint); |
| 169 | maskRect.offset (gc.clip_x_origin, | ||
| 170 | gc.clip_y_origin); | ||
| 203 | 171 | ||
| 204 | /* Set the transfer mode to SRC_IN to preserve only the parts | 172 | /* Set the transfer mode to SRC_IN to preserve only the parts |
| 205 | of the source that overlap with the mask. */ | 173 | of the source that overlap with the mask. */ |
| 206 | maskPaint = new Paint (); | 174 | maskPaint.setXfermode (EmacsGC.srcInAlu); |
| 207 | maskPaint.setXfermode (srcInAlu); | ||
| 208 | 175 | ||
| 209 | /* Draw the source. */ | 176 | /* Draw the source. */ |
| 210 | maskDestRect = new Rect (0, 0, srcRect.width (), | 177 | maskDestRect = new Rect (0, 0, srcRect.width (), |
| @@ -215,6 +182,10 @@ public class EmacsCopyArea implements EmacsPaintReq | |||
| 215 | /* Finally, draw the mask bitmap to the destination. */ | 182 | /* Finally, draw the mask bitmap to the destination. */ |
| 216 | paint.setXfermode (overAlu); | 183 | paint.setXfermode (overAlu); |
| 217 | canvas.drawBitmap (maskBitmap, null, maskRect, paint); | 184 | canvas.drawBitmap (maskBitmap, null, maskRect, paint); |
| 185 | gc.resetXfermode (); | ||
| 218 | } | 186 | } |
| 187 | |||
| 188 | canvas.restore (); | ||
| 189 | destination.damageRect (rect); | ||
| 219 | } | 190 | } |
| 220 | } | 191 | } |
diff --git a/java/org/gnu/emacs/EmacsDrawLine.java b/java/org/gnu/emacs/EmacsDrawLine.java index 6389031bbfa..8941d4c217f 100644 --- a/java/org/gnu/emacs/EmacsDrawLine.java +++ b/java/org/gnu/emacs/EmacsDrawLine.java | |||
| @@ -29,109 +29,49 @@ import android.graphics.PorterDuffXfermode; | |||
| 29 | import android.graphics.Rect; | 29 | import android.graphics.Rect; |
| 30 | import android.graphics.Xfermode; | 30 | import android.graphics.Xfermode; |
| 31 | 31 | ||
| 32 | public class EmacsDrawLine implements EmacsPaintReq | 32 | public class EmacsDrawLine |
| 33 | { | 33 | { |
| 34 | private int x, y, x2, y2; | 34 | public static void |
| 35 | private EmacsDrawable drawable; | 35 | perform (EmacsDrawable drawable, EmacsGC gc, |
| 36 | private EmacsGC immutableGC; | 36 | int x, int y, int x2, int y2) |
| 37 | private static Xfermode xorAlu, srcInAlu; | ||
| 38 | |||
| 39 | static | ||
| 40 | { | 37 | { |
| 41 | xorAlu = new PorterDuffXfermode (Mode.XOR); | 38 | Rect rect; |
| 42 | srcInAlu = new PorterDuffXfermode (Mode.SRC_IN); | 39 | Canvas canvas; |
| 43 | }; | 40 | Paint paint; |
| 41 | int i; | ||
| 44 | 42 | ||
| 45 | public | 43 | /* TODO implement stippling. */ |
| 46 | EmacsDrawLine (EmacsDrawable drawable, int x, int y, | 44 | if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED) |
| 47 | int x2, int y2, EmacsGC immutableGC) | 45 | return; |
| 48 | { | ||
| 49 | this.drawable = drawable; | ||
| 50 | this.x = x; | ||
| 51 | this.y = y; | ||
| 52 | this.x2 = x2; | ||
| 53 | this.y2 = y2; | ||
| 54 | this.immutableGC = immutableGC; | ||
| 55 | } | ||
| 56 | 46 | ||
| 57 | @Override | 47 | paint = gc.gcPaint; |
| 58 | public Rect | 48 | rect = new Rect (Math.min (x, x2 + 1), |
| 59 | getRect () | ||
| 60 | { | ||
| 61 | return new Rect (Math.min (x, x2 + 1), | ||
| 62 | Math.min (y, y2 + 1), | 49 | Math.min (y, y2 + 1), |
| 63 | Math.max (x2 + 1, x), | 50 | Math.max (x2 + 1, x), |
| 64 | Math.max (y2 + 1, y)); | 51 | Math.max (y2 + 1, y)); |
| 65 | } | 52 | canvas = drawable.lockCanvas (); |
| 66 | |||
| 67 | @Override | ||
| 68 | public EmacsDrawable | ||
| 69 | getDrawable () | ||
| 70 | { | ||
| 71 | return drawable; | ||
| 72 | } | ||
| 73 | |||
| 74 | @Override | ||
| 75 | public EmacsGC | ||
| 76 | getGC () | ||
| 77 | { | ||
| 78 | return immutableGC; | ||
| 79 | } | ||
| 80 | |||
| 81 | @Override | ||
| 82 | public void | ||
| 83 | paintTo (Canvas canvas, Paint paint, EmacsGC immutableGC) | ||
| 84 | { | ||
| 85 | int alu; | ||
| 86 | Paint maskPaint; | ||
| 87 | Canvas maskCanvas; | ||
| 88 | Bitmap maskBitmap; | ||
| 89 | Rect rect, srcRect; | ||
| 90 | int width, height; | ||
| 91 | 53 | ||
| 92 | /* TODO implement stippling. */ | 54 | if (canvas == null) |
| 93 | if (immutableGC.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED) | ||
| 94 | return; | 55 | return; |
| 95 | 56 | ||
| 96 | alu = immutableGC.function; | 57 | canvas.save (); |
| 97 | rect = getRect (); | ||
| 98 | width = rect.width (); | ||
| 99 | height = rect.height (); | ||
| 100 | |||
| 101 | paint.setStyle (Paint.Style.STROKE); | ||
| 102 | |||
| 103 | if (alu == EmacsGC.GC_COPY) | ||
| 104 | paint.setXfermode (null); | ||
| 105 | else | ||
| 106 | paint.setXfermode (xorAlu); | ||
| 107 | 58 | ||
| 108 | if (immutableGC.clip_mask == null) | 59 | if (gc.real_clip_rects != null) |
| 109 | { | ||
| 110 | paint.setColor (immutableGC.foreground | 0xff000000); | ||
| 111 | canvas.drawLine ((float) x, (float) y, | ||
| 112 | (float) x2, (float) y2, | ||
| 113 | paint); | ||
| 114 | } | ||
| 115 | else | ||
| 116 | { | 60 | { |
| 117 | maskPaint = new Paint (); | 61 | for (i = 0; i < gc.real_clip_rects.length; ++i) |
| 118 | maskBitmap | 62 | canvas.clipRect (gc.real_clip_rects[i]); |
| 119 | = immutableGC.clip_mask.bitmap.copy (Bitmap.Config.ARGB_8888, | ||
| 120 | true); | ||
| 121 | |||
| 122 | if (maskBitmap == null) | ||
| 123 | return; | ||
| 124 | |||
| 125 | maskPaint.setXfermode (srcInAlu); | ||
| 126 | maskPaint.setColor (immutableGC.foreground | 0xff000000); | ||
| 127 | maskCanvas = new Canvas (maskBitmap); | ||
| 128 | srcRect = new Rect (0, 0, maskBitmap.getWidth (), | ||
| 129 | maskBitmap.getHeight ()); | ||
| 130 | maskCanvas.drawLine (0.0f, 0.0f, (float) Math.abs (x - x2), | ||
| 131 | (float) Math.abs (y - y2), maskPaint); | ||
| 132 | canvas.drawBitmap (maskBitmap, srcRect, rect, paint); | ||
| 133 | } | 63 | } |
| 134 | 64 | ||
| 135 | paint.setXfermode (null); | 65 | paint.setStyle (Paint.Style.STROKE); |
| 66 | |||
| 67 | if (gc.clip_mask == null) | ||
| 68 | canvas.drawLine ((float) x, (float) y, | ||
| 69 | (float) x2, (float) y2, | ||
| 70 | paint); | ||
| 71 | |||
| 72 | /* DrawLine with clip mask not implemented; it is not used by | ||
| 73 | Emacs. */ | ||
| 74 | canvas.restore (); | ||
| 75 | drawable.damageRect (rect); | ||
| 136 | } | 76 | } |
| 137 | } | 77 | } |
diff --git a/java/org/gnu/emacs/EmacsDrawPoint.java b/java/org/gnu/emacs/EmacsDrawPoint.java index 772757ff424..3bc7be17961 100644 --- a/java/org/gnu/emacs/EmacsDrawPoint.java +++ b/java/org/gnu/emacs/EmacsDrawPoint.java | |||
| @@ -19,12 +19,13 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 19 | 19 | ||
| 20 | package org.gnu.emacs; | 20 | package org.gnu.emacs; |
| 21 | 21 | ||
| 22 | public class EmacsDrawPoint extends EmacsDrawRectangle | 22 | public class EmacsDrawPoint |
| 23 | { | 23 | { |
| 24 | public | 24 | public static void |
| 25 | EmacsDrawPoint (EmacsDrawable drawable, int x, int y, | 25 | perform (EmacsDrawable drawable, |
| 26 | EmacsGC immutableGC) | 26 | EmacsGC immutableGC, int x, int y) |
| 27 | { | 27 | { |
| 28 | super (drawable, x, y, 1, 1, immutableGC); | 28 | EmacsDrawRectangle.perform (drawable, immutableGC, |
| 29 | x, y, 1, 1); | ||
| 29 | } | 30 | } |
| 30 | } | 31 | } |
diff --git a/java/org/gnu/emacs/EmacsDrawRectangle.java b/java/org/gnu/emacs/EmacsDrawRectangle.java index e3f28227146..b42e9556e8c 100644 --- a/java/org/gnu/emacs/EmacsDrawRectangle.java +++ b/java/org/gnu/emacs/EmacsDrawRectangle.java | |||
| @@ -22,110 +22,104 @@ package org.gnu.emacs; | |||
| 22 | import android.graphics.Bitmap; | 22 | import android.graphics.Bitmap; |
| 23 | import android.graphics.Canvas; | 23 | import android.graphics.Canvas; |
| 24 | import android.graphics.Paint; | 24 | import android.graphics.Paint; |
| 25 | import android.graphics.PorterDuff.Mode; | ||
| 26 | import android.graphics.PorterDuffXfermode; | ||
| 27 | import android.graphics.Rect; | 25 | import android.graphics.Rect; |
| 28 | import android.graphics.Xfermode; | ||
| 29 | 26 | ||
| 30 | public class EmacsDrawRectangle implements EmacsPaintReq | 27 | import android.util.Log; |
| 31 | { | ||
| 32 | private int x, y, width, height; | ||
| 33 | private EmacsDrawable drawable; | ||
| 34 | private EmacsGC immutableGC; | ||
| 35 | private static Xfermode xorAlu, srcInAlu; | ||
| 36 | |||
| 37 | static | ||
| 38 | { | ||
| 39 | xorAlu = new PorterDuffXfermode (Mode.XOR); | ||
| 40 | srcInAlu = new PorterDuffXfermode (Mode.SRC_IN); | ||
| 41 | }; | ||
| 42 | |||
| 43 | public | ||
| 44 | EmacsDrawRectangle (EmacsDrawable drawable, int x, int y, | ||
| 45 | int width, int height, | ||
| 46 | EmacsGC immutableGC) | ||
| 47 | { | ||
| 48 | this.drawable = drawable; | ||
| 49 | this.x = x; | ||
| 50 | this.y = y; | ||
| 51 | this.width = width; | ||
| 52 | this.height = height; | ||
| 53 | this.immutableGC = immutableGC; | ||
| 54 | } | ||
| 55 | 28 | ||
| 56 | @Override | 29 | public class EmacsDrawRectangle |
| 57 | public Rect | 30 | { |
| 58 | getRect () | 31 | public static void |
| 59 | { | 32 | perform (EmacsDrawable drawable, EmacsGC gc, |
| 60 | /* Canvas.drawRect actually behaves exactly like PolyRectangle wrt | 33 | int x, int y, int width, int height) |
| 61 | to where the lines are placed, so extend the width and height | ||
| 62 | by 1 in the damage rectangle. */ | ||
| 63 | return new Rect (x, y, x + width + 1, y + height + 1); | ||
| 64 | } | ||
| 65 | |||
| 66 | @Override | ||
| 67 | public EmacsDrawable | ||
| 68 | getDrawable () | ||
| 69 | { | ||
| 70 | return drawable; | ||
| 71 | } | ||
| 72 | |||
| 73 | @Override | ||
| 74 | public EmacsGC | ||
| 75 | getGC () | ||
| 76 | { | ||
| 77 | return immutableGC; | ||
| 78 | } | ||
| 79 | |||
| 80 | @Override | ||
| 81 | public void | ||
| 82 | paintTo (Canvas canvas, Paint paint, EmacsGC immutableGC) | ||
| 83 | { | 34 | { |
| 84 | int alu; | 35 | int i; |
| 85 | Paint maskPaint; | 36 | Paint maskPaint, paint; |
| 86 | Canvas maskCanvas; | 37 | Canvas maskCanvas; |
| 87 | Bitmap maskBitmap; | 38 | Bitmap maskBitmap; |
| 88 | Rect rect, srcRect; | 39 | Rect rect; |
| 40 | Rect maskRect, dstRect; | ||
| 41 | Canvas canvas; | ||
| 42 | Bitmap clipBitmap; | ||
| 89 | 43 | ||
| 90 | /* TODO implement stippling. */ | 44 | /* TODO implement stippling. */ |
| 91 | if (immutableGC.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED) | 45 | if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED) |
| 92 | return; | 46 | return; |
| 93 | 47 | ||
| 94 | alu = immutableGC.function; | 48 | canvas = drawable.lockCanvas (); |
| 95 | rect = new Rect (x, y, x + width, y + height); | ||
| 96 | 49 | ||
| 97 | paint.setStyle (Paint.Style.STROKE); | 50 | if (canvas == null) |
| 98 | paint.setStrokeWidth (1); | 51 | return; |
| 99 | 52 | ||
| 100 | if (alu == EmacsGC.GC_COPY) | 53 | canvas.save (); |
| 101 | paint.setXfermode (null); | ||
| 102 | else | ||
| 103 | paint.setXfermode (xorAlu); | ||
| 104 | 54 | ||
| 105 | if (immutableGC.clip_mask == null) | 55 | if (gc.real_clip_rects != null) |
| 106 | { | 56 | { |
| 107 | paint.setColor (immutableGC.foreground | 0xff000000); | 57 | for (i = 0; i < gc.real_clip_rects.length; ++i) |
| 108 | canvas.drawRect (rect, paint); | 58 | canvas.clipRect (gc.real_clip_rects[i]); |
| 109 | } | 59 | } |
| 60 | |||
| 61 | paint = gc.gcPaint; | ||
| 62 | rect = new Rect (x, y, x + width, y + height); | ||
| 63 | |||
| 64 | paint.setStyle (Paint.Style.STROKE); | ||
| 65 | |||
| 66 | if (gc.clip_mask == null) | ||
| 67 | canvas.drawRect (rect, paint); | ||
| 110 | else | 68 | else |
| 111 | { | 69 | { |
| 112 | maskPaint = new Paint (); | 70 | /* Drawing with a clip mask involves calculating the |
| 113 | maskBitmap | 71 | intersection of the clip mask with the dst rect, and |
| 114 | = immutableGC.clip_mask.bitmap.copy (Bitmap.Config.ARGB_8888, | 72 | extrapolating the corresponding part of the src rect. */ |
| 115 | true); | 73 | clipBitmap = gc.clip_mask.bitmap; |
| 116 | 74 | dstRect = new Rect (x, y, x + width, y + height); | |
| 117 | if (maskBitmap == null) | 75 | maskRect = new Rect (gc.clip_x_origin, |
| 76 | gc.clip_y_origin, | ||
| 77 | (gc.clip_x_origin | ||
| 78 | + clipBitmap.getWidth ()), | ||
| 79 | (gc.clip_y_origin | ||
| 80 | + clipBitmap.getHeight ())); | ||
| 81 | clipBitmap = gc.clip_mask.bitmap; | ||
| 82 | |||
| 83 | if (!maskRect.setIntersect (dstRect, maskRect)) | ||
| 84 | /* There is no intersection between the clip mask and the | ||
| 85 | dest rect. */ | ||
| 118 | return; | 86 | return; |
| 119 | 87 | ||
| 120 | maskPaint.setXfermode (srcInAlu); | 88 | /* Finally, create a temporary bitmap that is the size of |
| 121 | maskPaint.setColor (immutableGC.foreground | 0xff000000); | 89 | maskRect. */ |
| 90 | |||
| 91 | maskBitmap | ||
| 92 | = Bitmap.createBitmap (maskRect.width (), maskRect.height (), | ||
| 93 | Bitmap.Config.ARGB_8888); | ||
| 94 | |||
| 95 | /* Draw the mask onto the maskBitmap. */ | ||
| 122 | maskCanvas = new Canvas (maskBitmap); | 96 | maskCanvas = new Canvas (maskBitmap); |
| 123 | srcRect = new Rect (0, 0, maskBitmap.getWidth (), | 97 | maskRect.offset (-gc.clip_x_origin, |
| 124 | maskBitmap.getHeight ()); | 98 | -gc.clip_y_origin); |
| 125 | maskCanvas.drawRect (srcRect, maskPaint); | 99 | maskCanvas.drawBitmap (gc.clip_mask.bitmap, |
| 126 | canvas.drawBitmap (maskBitmap, srcRect, rect, paint); | 100 | maskRect, new Rect (0, 0, |
| 101 | maskRect.width (), | ||
| 102 | maskRect.height ()), | ||
| 103 | paint); | ||
| 104 | maskRect.offset (gc.clip_x_origin, | ||
| 105 | gc.clip_y_origin); | ||
| 106 | |||
| 107 | /* Set the transfer mode to SRC_IN to preserve only the parts | ||
| 108 | of the source that overlap with the mask. */ | ||
| 109 | maskPaint = new Paint (); | ||
| 110 | maskPaint.setXfermode (EmacsGC.srcInAlu); | ||
| 111 | maskPaint.setStyle (Paint.Style.STROKE); | ||
| 112 | |||
| 113 | /* Draw the source. */ | ||
| 114 | maskCanvas.drawRect (maskRect, maskPaint); | ||
| 115 | |||
| 116 | /* Finally, draw the mask bitmap to the destination. */ | ||
| 117 | paint.setXfermode (null); | ||
| 118 | canvas.drawBitmap (maskBitmap, null, maskRect, paint); | ||
| 127 | } | 119 | } |
| 128 | 120 | ||
| 129 | paint.setXfermode (null); | 121 | canvas.restore (); |
| 122 | drawable.damageRect (new Rect (x, y, x + width + 1, | ||
| 123 | y + height + 1)); | ||
| 130 | } | 124 | } |
| 131 | } | 125 | } |
diff --git a/java/org/gnu/emacs/EmacsDrawable.java b/java/org/gnu/emacs/EmacsDrawable.java index 19062137213..6a6199ff214 100644 --- a/java/org/gnu/emacs/EmacsDrawable.java +++ b/java/org/gnu/emacs/EmacsDrawable.java | |||
| @@ -26,7 +26,6 @@ import android.graphics.Canvas; | |||
| 26 | public interface EmacsDrawable | 26 | public interface EmacsDrawable |
| 27 | { | 27 | { |
| 28 | public Canvas lockCanvas (); | 28 | public Canvas lockCanvas (); |
| 29 | public void unlockCanvas (); | ||
| 30 | public void damageRect (Rect damageRect); | 29 | public void damageRect (Rect damageRect); |
| 31 | public Bitmap getBitmap (); | 30 | public Bitmap getBitmap (); |
| 32 | public boolean isDestroyed (); | 31 | public boolean isDestroyed (); |
diff --git a/java/org/gnu/emacs/EmacsFillPolygon.java b/java/org/gnu/emacs/EmacsFillPolygon.java index 3198c7f07c4..42b73886dff 100644 --- a/java/org/gnu/emacs/EmacsFillPolygon.java +++ b/java/org/gnu/emacs/EmacsFillPolygon.java | |||
| @@ -26,34 +26,35 @@ import android.graphics.Canvas; | |||
| 26 | import android.graphics.Paint; | 26 | import android.graphics.Paint; |
| 27 | import android.graphics.Path; | 27 | import android.graphics.Path; |
| 28 | import android.graphics.Point; | 28 | import android.graphics.Point; |
| 29 | import android.graphics.PorterDuff.Mode; | ||
| 30 | import android.graphics.PorterDuffXfermode; | ||
| 31 | import android.graphics.Rect; | 29 | import android.graphics.Rect; |
| 32 | import android.graphics.RectF; | 30 | import android.graphics.RectF; |
| 33 | import android.graphics.Xfermode; | ||
| 34 | 31 | ||
| 35 | public class EmacsFillPolygon implements EmacsPaintReq | 32 | public class EmacsFillPolygon |
| 36 | { | 33 | { |
| 37 | private EmacsDrawable drawable; | 34 | public static void |
| 38 | private EmacsGC immutableGC; | 35 | perform (EmacsDrawable drawable, EmacsGC gc, Point points[]) |
| 39 | private Path path; | 36 | { |
| 37 | Canvas canvas; | ||
| 38 | Path path; | ||
| 39 | Paint paint; | ||
| 40 | Rect rect; | ||
| 41 | RectF rectF; | ||
| 42 | int i; | ||
| 40 | 43 | ||
| 41 | private static Xfermode xorAlu, srcInAlu; | 44 | canvas = drawable.lockCanvas (); |
| 42 | 45 | ||
| 43 | static | 46 | if (canvas == null) |
| 44 | { | 47 | return; |
| 45 | xorAlu = new PorterDuffXfermode (Mode.XOR); | ||
| 46 | srcInAlu = new PorterDuffXfermode (Mode.SRC_IN); | ||
| 47 | }; | ||
| 48 | 48 | ||
| 49 | public | 49 | paint = gc.gcPaint; |
| 50 | EmacsFillPolygon (EmacsDrawable drawable, Point points[], | 50 | |
| 51 | EmacsGC immutableGC) | 51 | canvas.save (); |
| 52 | { | ||
| 53 | int i; | ||
| 54 | 52 | ||
| 55 | this.drawable = drawable; | 53 | if (gc.real_clip_rects != null) |
| 56 | this.immutableGC = immutableGC; | 54 | { |
| 55 | for (i = 0; i < gc.real_clip_rects.length; ++i) | ||
| 56 | canvas.clipRect (gc.real_clip_rects[i]); | ||
| 57 | } | ||
| 57 | 58 | ||
| 58 | /* Build the path from the given array of points. */ | 59 | /* Build the path from the given array of points. */ |
| 59 | path = new Path (); | 60 | path = new Path (); |
| @@ -67,84 +68,25 @@ public class EmacsFillPolygon implements EmacsPaintReq | |||
| 67 | 68 | ||
| 68 | path.close (); | 69 | path.close (); |
| 69 | } | 70 | } |
| 70 | } | ||
| 71 | |||
| 72 | @Override | ||
| 73 | public Rect | ||
| 74 | getRect () | ||
| 75 | { | ||
| 76 | RectF rect; | ||
| 77 | 71 | ||
| 78 | rect = new RectF (0, 0, 0, 0); | 72 | /* Compute the damage rectangle. */ |
| 79 | path.computeBounds (rect, true); | 73 | rectF = new RectF (0, 0, 0, 0); |
| 74 | path.computeBounds (rectF, true); | ||
| 80 | 75 | ||
| 81 | return new Rect ((int) Math.floor (rect.left), | 76 | rect = new Rect ((int) Math.floor (rectF.left), |
| 82 | (int) Math.floor (rect.top), | 77 | (int) Math.floor (rectF.top), |
| 83 | (int) Math.ceil (rect.right), | 78 | (int) Math.ceil (rectF.right), |
| 84 | (int) Math.ceil (rect.bottom)); | 79 | (int) Math.ceil (rectF.bottom)); |
| 85 | } | ||
| 86 | 80 | ||
| 87 | @Override | 81 | paint.setStyle (Paint.Style.FILL); |
| 88 | public EmacsDrawable | ||
| 89 | getDrawable () | ||
| 90 | { | ||
| 91 | return drawable; | ||
| 92 | } | ||
| 93 | |||
| 94 | @Override | ||
| 95 | public EmacsGC | ||
| 96 | getGC () | ||
| 97 | { | ||
| 98 | return immutableGC; | ||
| 99 | } | ||
| 100 | |||
| 101 | @Override | ||
| 102 | public void | ||
| 103 | paintTo (Canvas canvas, Paint paint, EmacsGC immutableGC) | ||
| 104 | { | ||
| 105 | int alu; | ||
| 106 | Paint maskPaint; | ||
| 107 | Canvas maskCanvas; | ||
| 108 | Bitmap maskBitmap; | ||
| 109 | Rect rect; | ||
| 110 | |||
| 111 | /* TODO implement stippling. */ | ||
| 112 | if (immutableGC.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED) | ||
| 113 | return; | ||
| 114 | |||
| 115 | alu = immutableGC.function; | ||
| 116 | rect = getRect (); | ||
| 117 | 82 | ||
| 118 | if (alu == EmacsGC.GC_COPY) | 83 | if (gc.clip_mask == null) |
| 119 | paint.setXfermode (null); | 84 | canvas.drawPath (path, paint); |
| 120 | else | ||
| 121 | paint.setXfermode (xorAlu); | ||
| 122 | 85 | ||
| 123 | paint.setStyle (Paint.Style.FILL); | 86 | canvas.restore (); |
| 87 | drawable.damageRect (rect); | ||
| 124 | 88 | ||
| 125 | if (immutableGC.clip_mask == null) | 89 | /* FillPolygon with clip mask not implemented; it is not used by |
| 126 | { | 90 | Emacs. */ |
| 127 | paint.setColor (immutableGC.foreground | 0xff000000); | ||
| 128 | canvas.drawPath (path, paint); | ||
| 129 | } | ||
| 130 | else | ||
| 131 | { | ||
| 132 | maskPaint = new Paint (); | ||
| 133 | maskBitmap = immutableGC.clip_mask.bitmap; | ||
| 134 | maskBitmap = maskBitmap.copy (Bitmap.Config.ARGB_8888, | ||
| 135 | true); | ||
| 136 | |||
| 137 | if (maskBitmap == null) | ||
| 138 | return; | ||
| 139 | |||
| 140 | maskPaint.setXfermode (srcInAlu); | ||
| 141 | maskPaint.setColor (immutableGC.foreground | 0xff000000); | ||
| 142 | maskCanvas = new Canvas (maskBitmap); | ||
| 143 | path.offset (-rect.left, -rect.top, null); | ||
| 144 | maskCanvas.drawPath (path, maskPaint); | ||
| 145 | canvas.drawBitmap (maskBitmap, new Rect (0, 0, rect.width (), | ||
| 146 | rect.height ()), | ||
| 147 | rect, paint); | ||
| 148 | } | ||
| 149 | } | 91 | } |
| 150 | } | 92 | } |
diff --git a/java/org/gnu/emacs/EmacsFillRectangle.java b/java/org/gnu/emacs/EmacsFillRectangle.java index 7246c13de7f..b733b417d6b 100644 --- a/java/org/gnu/emacs/EmacsFillRectangle.java +++ b/java/org/gnu/emacs/EmacsFillRectangle.java | |||
| @@ -22,108 +22,102 @@ package org.gnu.emacs; | |||
| 22 | import android.graphics.Bitmap; | 22 | import android.graphics.Bitmap; |
| 23 | import android.graphics.Canvas; | 23 | import android.graphics.Canvas; |
| 24 | import android.graphics.Paint; | 24 | import android.graphics.Paint; |
| 25 | import android.graphics.PorterDuff.Mode; | ||
| 26 | import android.graphics.PorterDuffXfermode; | ||
| 27 | import android.graphics.Rect; | 25 | import android.graphics.Rect; |
| 28 | import android.graphics.Xfermode; | ||
| 29 | 26 | ||
| 30 | import android.util.Log; | 27 | import android.util.Log; |
| 31 | 28 | ||
| 32 | public class EmacsFillRectangle implements EmacsPaintReq | 29 | public class EmacsFillRectangle |
| 33 | { | 30 | { |
| 34 | private int x, y, width, height; | 31 | public static void |
| 35 | private EmacsDrawable drawable; | 32 | perform (EmacsDrawable drawable, EmacsGC gc, |
| 36 | private EmacsGC immutableGC; | 33 | int x, int y, int width, int height) |
| 37 | private static Xfermode xorAlu, srcInAlu; | ||
| 38 | |||
| 39 | static | ||
| 40 | { | ||
| 41 | xorAlu = new PorterDuffXfermode (Mode.XOR); | ||
| 42 | srcInAlu = new PorterDuffXfermode (Mode.SRC_IN); | ||
| 43 | }; | ||
| 44 | |||
| 45 | public | ||
| 46 | EmacsFillRectangle (EmacsDrawable drawable, int x, int y, | ||
| 47 | int width, int height, | ||
| 48 | EmacsGC immutableGC) | ||
| 49 | { | ||
| 50 | this.drawable = drawable; | ||
| 51 | this.x = x; | ||
| 52 | this.y = y; | ||
| 53 | this.width = width; | ||
| 54 | this.height = height; | ||
| 55 | this.immutableGC = immutableGC; | ||
| 56 | } | ||
| 57 | |||
| 58 | @Override | ||
| 59 | public Rect | ||
| 60 | getRect () | ||
| 61 | { | ||
| 62 | return new Rect (x, y, x + width, y + height); | ||
| 63 | } | ||
| 64 | |||
| 65 | @Override | ||
| 66 | public EmacsDrawable | ||
| 67 | getDrawable () | ||
| 68 | { | 34 | { |
| 69 | return drawable; | 35 | int i; |
| 70 | } | 36 | Paint maskPaint, paint; |
| 71 | |||
| 72 | @Override | ||
| 73 | public EmacsGC | ||
| 74 | getGC () | ||
| 75 | { | ||
| 76 | return immutableGC; | ||
| 77 | } | ||
| 78 | |||
| 79 | @Override | ||
| 80 | public void | ||
| 81 | paintTo (Canvas canvas, Paint paint, EmacsGC immutableGC) | ||
| 82 | { | ||
| 83 | int alu; | ||
| 84 | Paint maskPaint; | ||
| 85 | Canvas maskCanvas; | 37 | Canvas maskCanvas; |
| 86 | Bitmap maskBitmap; | 38 | Bitmap maskBitmap; |
| 87 | Rect rect, srcRect; | 39 | Rect rect; |
| 40 | Rect maskRect, dstRect; | ||
| 41 | Canvas canvas; | ||
| 42 | Bitmap clipBitmap; | ||
| 88 | 43 | ||
| 89 | /* TODO implement stippling. */ | 44 | /* TODO implement stippling. */ |
| 90 | if (immutableGC.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED) | 45 | if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED) |
| 91 | return; | 46 | return; |
| 92 | 47 | ||
| 93 | alu = immutableGC.function; | 48 | canvas = drawable.lockCanvas (); |
| 94 | rect = getRect (); | ||
| 95 | 49 | ||
| 96 | paint.setStyle (Paint.Style.FILL); | 50 | if (canvas == null) |
| 51 | return; | ||
| 97 | 52 | ||
| 98 | if (alu == EmacsGC.GC_COPY) | 53 | canvas.save (); |
| 99 | paint.setXfermode (null); | ||
| 100 | else | ||
| 101 | paint.setXfermode (xorAlu); | ||
| 102 | 54 | ||
| 103 | if (immutableGC.clip_mask == null) | 55 | if (gc.real_clip_rects != null) |
| 104 | { | 56 | { |
| 105 | paint.setColor (immutableGC.foreground | 0xff000000); | 57 | for (i = 0; i < gc.real_clip_rects.length; ++i) |
| 106 | canvas.drawRect (rect, paint); | 58 | canvas.clipRect (gc.real_clip_rects[i]); |
| 107 | } | 59 | } |
| 60 | |||
| 61 | paint = gc.gcPaint; | ||
| 62 | rect = new Rect (x, y, x + width, y + height); | ||
| 63 | |||
| 64 | paint.setStyle (Paint.Style.FILL); | ||
| 65 | |||
| 66 | if (gc.clip_mask == null) | ||
| 67 | canvas.drawRect (rect, paint); | ||
| 108 | else | 68 | else |
| 109 | { | 69 | { |
| 110 | maskPaint = new Paint (); | 70 | /* Drawing with a clip mask involves calculating the |
| 111 | maskBitmap | 71 | intersection of the clip mask with the dst rect, and |
| 112 | = immutableGC.clip_mask.bitmap.copy (Bitmap.Config.ARGB_8888, | 72 | extrapolating the corresponding part of the src rect. */ |
| 113 | true); | 73 | clipBitmap = gc.clip_mask.bitmap; |
| 114 | 74 | dstRect = new Rect (x, y, x + width, y + height); | |
| 115 | if (maskBitmap == null) | 75 | maskRect = new Rect (gc.clip_x_origin, |
| 76 | gc.clip_y_origin, | ||
| 77 | (gc.clip_x_origin | ||
| 78 | + clipBitmap.getWidth ()), | ||
| 79 | (gc.clip_y_origin | ||
| 80 | + clipBitmap.getHeight ())); | ||
| 81 | clipBitmap = gc.clip_mask.bitmap; | ||
| 82 | |||
| 83 | if (!maskRect.setIntersect (dstRect, maskRect)) | ||
| 84 | /* There is no intersection between the clip mask and the | ||
| 85 | dest rect. */ | ||
| 116 | return; | 86 | return; |
| 117 | 87 | ||
| 118 | maskPaint.setXfermode (srcInAlu); | 88 | /* Finally, create a temporary bitmap that is the size of |
| 119 | maskPaint.setColor (immutableGC.foreground | 0xff000000); | 89 | maskRect. */ |
| 90 | |||
| 91 | maskBitmap | ||
| 92 | = Bitmap.createBitmap (maskRect.width (), maskRect.height (), | ||
| 93 | Bitmap.Config.ARGB_8888); | ||
| 94 | |||
| 95 | /* Draw the mask onto the maskBitmap. */ | ||
| 120 | maskCanvas = new Canvas (maskBitmap); | 96 | maskCanvas = new Canvas (maskBitmap); |
| 121 | srcRect = new Rect (0, 0, maskBitmap.getWidth (), | 97 | maskRect.offset (-gc.clip_x_origin, |
| 122 | maskBitmap.getHeight ()); | 98 | -gc.clip_y_origin); |
| 123 | maskCanvas.drawRect (srcRect, maskPaint); | 99 | maskCanvas.drawBitmap (gc.clip_mask.bitmap, |
| 124 | canvas.drawBitmap (maskBitmap, srcRect, rect, paint); | 100 | maskRect, new Rect (0, 0, |
| 101 | maskRect.width (), | ||
| 102 | maskRect.height ()), | ||
| 103 | paint); | ||
| 104 | maskRect.offset (gc.clip_x_origin, | ||
| 105 | gc.clip_y_origin); | ||
| 106 | |||
| 107 | /* Set the transfer mode to SRC_IN to preserve only the parts | ||
| 108 | of the source that overlap with the mask. */ | ||
| 109 | maskPaint = new Paint (); | ||
| 110 | maskPaint.setXfermode (EmacsGC.srcInAlu); | ||
| 111 | |||
| 112 | /* Draw the source. */ | ||
| 113 | maskCanvas.drawRect (maskRect, maskPaint); | ||
| 114 | |||
| 115 | /* Finally, draw the mask bitmap to the destination. */ | ||
| 116 | paint.setXfermode (null); | ||
| 117 | canvas.drawBitmap (maskBitmap, null, maskRect, paint); | ||
| 125 | } | 118 | } |
| 126 | 119 | ||
| 127 | paint.setXfermode (null); | 120 | canvas.restore (); |
| 121 | drawable.damageRect (rect); | ||
| 128 | } | 122 | } |
| 129 | } | 123 | } |
diff --git a/java/org/gnu/emacs/EmacsFontDriver.java b/java/org/gnu/emacs/EmacsFontDriver.java index 9f40aa04c44..1d1e6f7b33f 100644 --- a/java/org/gnu/emacs/EmacsFontDriver.java +++ b/java/org/gnu/emacs/EmacsFontDriver.java | |||
| @@ -164,7 +164,7 @@ public abstract class EmacsFontDriver | |||
| 164 | public static EmacsFontDriver | 164 | public static EmacsFontDriver |
| 165 | createFontDriver () | 165 | createFontDriver () |
| 166 | { | 166 | { |
| 167 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.M) | 167 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) |
| 168 | return new EmacsSdk23FontDriver (); | 168 | return new EmacsSdk23FontDriver (); |
| 169 | 169 | ||
| 170 | return new EmacsSdk7FontDriver (); | 170 | return new EmacsSdk7FontDriver (); |
diff --git a/java/org/gnu/emacs/EmacsGC.java b/java/org/gnu/emacs/EmacsGC.java index 0becb04519d..caa5c91edd4 100644 --- a/java/org/gnu/emacs/EmacsGC.java +++ b/java/org/gnu/emacs/EmacsGC.java | |||
| @@ -20,6 +20,11 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 20 | package org.gnu.emacs; | 20 | package org.gnu.emacs; |
| 21 | 21 | ||
| 22 | import android.graphics.Rect; | 22 | import android.graphics.Rect; |
| 23 | import android.graphics.Paint; | ||
| 24 | |||
| 25 | import android.graphics.PorterDuff.Mode; | ||
| 26 | import android.graphics.PorterDuffXfermode; | ||
| 27 | import android.graphics.Xfermode; | ||
| 23 | 28 | ||
| 24 | /* X like graphics context structures. Keep the enums in synch with | 29 | /* X like graphics context structures. Keep the enums in synch with |
| 25 | androidgui.h! */ | 30 | androidgui.h! */ |
| @@ -32,14 +37,21 @@ public class EmacsGC extends EmacsHandleObject | |||
| 32 | public static final int GC_FILL_SOLID = 0; | 37 | public static final int GC_FILL_SOLID = 0; |
| 33 | public static final int GC_FILL_OPAQUE_STIPPLED = 1; | 38 | public static final int GC_FILL_OPAQUE_STIPPLED = 1; |
| 34 | 39 | ||
| 40 | public static final Xfermode xorAlu, srcInAlu; | ||
| 41 | |||
| 35 | public int function, fill_style; | 42 | public int function, fill_style; |
| 36 | public int foreground, background; | 43 | public int foreground, background; |
| 37 | public int clip_x_origin, clip_y_origin; | 44 | public int clip_x_origin, clip_y_origin; |
| 38 | public int ts_origin_x, ts_origin_y; | 45 | public int ts_origin_x, ts_origin_y; |
| 39 | public Rect clip_rects[]; | 46 | public Rect clip_rects[], real_clip_rects[]; |
| 40 | public EmacsPixmap clip_mask, stipple; | 47 | public EmacsPixmap clip_mask, stipple; |
| 41 | private boolean dirty; | 48 | public Paint gcPaint; |
| 42 | private EmacsGC immutableGC; | 49 | |
| 50 | static | ||
| 51 | { | ||
| 52 | xorAlu = new PorterDuffXfermode (Mode.XOR); | ||
| 53 | srcInAlu = new PorterDuffXfermode (Mode.SRC_IN); | ||
| 54 | } | ||
| 43 | 55 | ||
| 44 | /* The following fields are only set on immutable GCs. */ | 56 | /* The following fields are only set on immutable GCs. */ |
| 45 | 57 | ||
| @@ -55,62 +67,41 @@ public class EmacsGC extends EmacsHandleObject | |||
| 55 | fill_style = GC_FILL_SOLID; | 67 | fill_style = GC_FILL_SOLID; |
| 56 | function = GC_COPY; | 68 | function = GC_COPY; |
| 57 | foreground = 0; | 69 | foreground = 0; |
| 58 | background = 0xffffffff; | 70 | background = 0xffffff; |
| 71 | gcPaint = new Paint (); | ||
| 59 | } | 72 | } |
| 60 | 73 | ||
| 61 | public | 74 | /* Mark this GC as dirty. Apply parameters to the paint and |
| 62 | EmacsGC (EmacsGC source) | 75 | recompute real_clip_rects. */ |
| 63 | { | ||
| 64 | super ((short) 0); | ||
| 65 | 76 | ||
| 77 | public void | ||
| 78 | markDirty () | ||
| 79 | { | ||
| 66 | int i; | 80 | int i; |
| 67 | 81 | ||
| 68 | function = source.function; | ||
| 69 | fill_style = source.fill_style; | ||
| 70 | foreground = source.foreground; | ||
| 71 | background = source.background; | ||
| 72 | clip_x_origin = source.clip_x_origin; | ||
| 73 | clip_y_origin = source.clip_y_origin; | ||
| 74 | clip_rects = source.clip_rects; | ||
| 75 | clip_mask = source.clip_mask; | ||
| 76 | stipple = source.stipple; | ||
| 77 | ts_origin_x = source.ts_origin_x; | ||
| 78 | ts_origin_y = source.ts_origin_y; | ||
| 79 | |||
| 80 | /* Offset all the clip rects by ts_origin_x and ts_origin_y. */ | ||
| 81 | |||
| 82 | if ((ts_origin_x != 0 || ts_origin_y != 0) | 82 | if ((ts_origin_x != 0 || ts_origin_y != 0) |
| 83 | && clip_rects != null) | 83 | && clip_rects != null) |
| 84 | { | 84 | { |
| 85 | clip_rects = new Rect[clip_rects.length]; | 85 | real_clip_rects = new Rect[clip_rects.length]; |
| 86 | 86 | ||
| 87 | for (i = 0; i < clip_rects.length; ++i) | 87 | for (i = 0; i < clip_rects.length; ++i) |
| 88 | { | 88 | { |
| 89 | clip_rects[i] = new Rect (source.clip_rects[i]); | 89 | real_clip_rects[i] = new Rect (clip_rects[i]); |
| 90 | clip_rects[i].offset (ts_origin_x, | 90 | real_clip_rects[i].offset (ts_origin_x, ts_origin_y); |
| 91 | ts_origin_y); | ||
| 92 | } | 91 | } |
| 93 | } | 92 | } |
| 94 | } | 93 | else |
| 94 | real_clip_rects = clip_rects; | ||
| 95 | 95 | ||
| 96 | /* Mark this GC as dirty. This means immutableGC will return a new | 96 | gcPaint.setColor (foreground | 0xff000000); |
| 97 | copy of this GC the next time it is called. */ | 97 | gcPaint.setXfermode (function == GC_XOR |
| 98 | ? xorAlu : srcInAlu); | ||
| 99 | } | ||
| 98 | 100 | ||
| 99 | public void | 101 | public void |
| 100 | markDirty () | 102 | resetXfermode () |
| 101 | { | 103 | { |
| 102 | dirty = true; | 104 | gcPaint.setXfermode (function == GC_XOR |
| 105 | ? xorAlu : srcInAlu); | ||
| 103 | } | 106 | } |
| 104 | |||
| 105 | public EmacsGC | ||
| 106 | immutableGC () | ||
| 107 | { | ||
| 108 | if (immutableGC == null || dirty) | ||
| 109 | { | ||
| 110 | immutableGC = new EmacsGC (this); | ||
| 111 | dirty = false; | ||
| 112 | } | ||
| 113 | |||
| 114 | return immutableGC; | ||
| 115 | }; | ||
| 116 | }; | 107 | }; |
diff --git a/java/org/gnu/emacs/EmacsNative.java b/java/org/gnu/emacs/EmacsNative.java index c80339031a8..ae48ce30408 100644 --- a/java/org/gnu/emacs/EmacsNative.java +++ b/java/org/gnu/emacs/EmacsNative.java | |||
| @@ -79,6 +79,28 @@ public class EmacsNative | |||
| 79 | /* Send an ANDROID_WINDOW_ACTION event. */ | 79 | /* Send an ANDROID_WINDOW_ACTION event. */ |
| 80 | public static native void sendWindowAction (short window, int action); | 80 | public static native void sendWindowAction (short window, int action); |
| 81 | 81 | ||
| 82 | /* Send an ANDROID_ENTER_NOTIFY event. */ | ||
| 83 | public static native void sendEnterNotify (short window, int x, int y, | ||
| 84 | long time); | ||
| 85 | |||
| 86 | /* Send an ANDROID_LEAVE_NOTIFY event. */ | ||
| 87 | public static native void sendLeaveNotify (short window, int x, int y, | ||
| 88 | long time); | ||
| 89 | |||
| 90 | /* Send an ANDROID_MOTION_NOTIFY event. */ | ||
| 91 | public static native void sendMotionNotify (short window, int x, int y, | ||
| 92 | long time); | ||
| 93 | |||
| 94 | /* Send an ANDROID_BUTTON_PRESS event. */ | ||
| 95 | public static native void sendButtonPress (short window, int x, int y, | ||
| 96 | long time, int state, | ||
| 97 | int button); | ||
| 98 | |||
| 99 | /* Send an ANDROID_BUTTON_RELEASE event. */ | ||
| 100 | public static native void sendButtonRelease (short window, int x, int y, | ||
| 101 | long time, int state, | ||
| 102 | int button); | ||
| 103 | |||
| 82 | static | 104 | static |
| 83 | { | 105 | { |
| 84 | System.loadLibrary ("emacs"); | 106 | System.loadLibrary ("emacs"); |
diff --git a/java/org/gnu/emacs/EmacsPixmap.java b/java/org/gnu/emacs/EmacsPixmap.java index 897902c5b57..15452f007c4 100644 --- a/java/org/gnu/emacs/EmacsPixmap.java +++ b/java/org/gnu/emacs/EmacsPixmap.java | |||
| @@ -93,6 +93,8 @@ public class EmacsPixmap extends EmacsHandleObject | |||
| 93 | break; | 93 | break; |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | bitmap.eraseColor (0xff000000); | ||
| 97 | |||
| 96 | this.width = width; | 98 | this.width = width; |
| 97 | this.height = height; | 99 | this.height = height; |
| 98 | this.depth = depth; | 100 | this.depth = depth; |
| @@ -110,13 +112,6 @@ public class EmacsPixmap extends EmacsHandleObject | |||
| 110 | 112 | ||
| 111 | @Override | 113 | @Override |
| 112 | public void | 114 | public void |
| 113 | unlockCanvas () | ||
| 114 | { | ||
| 115 | |||
| 116 | } | ||
| 117 | |||
| 118 | @Override | ||
| 119 | public void | ||
| 120 | damageRect (Rect damageRect) | 115 | damageRect (Rect damageRect) |
| 121 | { | 116 | { |
| 122 | 117 | ||
diff --git a/java/org/gnu/emacs/EmacsSdk23FontDriver.java b/java/org/gnu/emacs/EmacsSdk23FontDriver.java index 34e2b1803a2..11e128d5769 100644 --- a/java/org/gnu/emacs/EmacsSdk23FontDriver.java +++ b/java/org/gnu/emacs/EmacsSdk23FontDriver.java | |||
| @@ -20,9 +20,80 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 20 | package org.gnu.emacs; | 20 | package org.gnu.emacs; |
| 21 | 21 | ||
| 22 | import android.graphics.Paint; | 22 | import android.graphics.Paint; |
| 23 | import android.graphics.Rect; | ||
| 23 | 24 | ||
| 24 | public class EmacsSdk23FontDriver extends EmacsSdk7FontDriver | 25 | public class EmacsSdk23FontDriver extends EmacsSdk7FontDriver |
| 25 | { | 26 | { |
| 27 | private void | ||
| 28 | textExtents1 (Sdk7FontObject font, int code, FontMetrics metrics, | ||
| 29 | Paint paint, Rect bounds) | ||
| 30 | { | ||
| 31 | char[] text; | ||
| 32 | |||
| 33 | text = new char[2]; | ||
| 34 | text[0] = (char) code; | ||
| 35 | text[1] = 'c'; | ||
| 36 | |||
| 37 | paint.getTextBounds (text, 0, 1, bounds); | ||
| 38 | |||
| 39 | metrics.lbearing = (short) bounds.left; | ||
| 40 | metrics.rbearing = (short) bounds.right; | ||
| 41 | metrics.ascent = (short) -bounds.top; | ||
| 42 | metrics.descent = (short) bounds.bottom; | ||
| 43 | metrics.width | ||
| 44 | = (short) paint.getRunAdvance (text, 0, 1, 0, 1, false, 1); | ||
| 45 | } | ||
| 46 | |||
| 47 | @Override | ||
| 48 | public void | ||
| 49 | textExtents (FontObject font, int code[], FontMetrics fontMetrics) | ||
| 50 | { | ||
| 51 | int i; | ||
| 52 | Paint paintCache; | ||
| 53 | Rect boundsCache; | ||
| 54 | Sdk7FontObject fontObject; | ||
| 55 | char[] text; | ||
| 56 | float width; | ||
| 57 | |||
| 58 | fontObject = (Sdk7FontObject) font; | ||
| 59 | paintCache = fontObject.typeface.typefacePaint; | ||
| 60 | paintCache.setTextSize (fontObject.pixelSize); | ||
| 61 | boundsCache = new Rect (); | ||
| 62 | |||
| 63 | if (code.length == 0) | ||
| 64 | { | ||
| 65 | fontMetrics.lbearing = 0; | ||
| 66 | fontMetrics.rbearing = 0; | ||
| 67 | fontMetrics.ascent = 0; | ||
| 68 | fontMetrics.descent = 0; | ||
| 69 | fontMetrics.width = 0; | ||
| 70 | } | ||
| 71 | else if (code.length == 1) | ||
| 72 | textExtents1 ((Sdk7FontObject) font, code[0], fontMetrics, | ||
| 73 | paintCache, boundsCache); | ||
| 74 | else | ||
| 75 | { | ||
| 76 | text = new char[code.length + 1]; | ||
| 77 | |||
| 78 | for (i = 0; i < code.length; ++i) | ||
| 79 | text[i] = (char) code[i]; | ||
| 80 | |||
| 81 | text[code.length] = 'c'; | ||
| 82 | |||
| 83 | paintCache.getTextBounds (text, 0, code.length, | ||
| 84 | boundsCache); | ||
| 85 | width = paintCache.getRunAdvance (text, 0, code.length, 0, | ||
| 86 | code.length, | ||
| 87 | false, code.length); | ||
| 88 | |||
| 89 | fontMetrics.lbearing = (short) boundsCache.left; | ||
| 90 | fontMetrics.rbearing = (short) boundsCache.right; | ||
| 91 | fontMetrics.ascent = (short) -boundsCache.top; | ||
| 92 | fontMetrics.descent = (short) boundsCache.bottom; | ||
| 93 | fontMetrics.width = (short) width; | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 26 | @Override | 97 | @Override |
| 27 | public int | 98 | public int |
| 28 | hasChar (FontSpec font, char charCode) | 99 | hasChar (FontSpec font, char charCode) |
diff --git a/java/org/gnu/emacs/EmacsSdk7FontDriver.java b/java/org/gnu/emacs/EmacsSdk7FontDriver.java index 437f38e62db..8a9426050ae 100644 --- a/java/org/gnu/emacs/EmacsSdk7FontDriver.java +++ b/java/org/gnu/emacs/EmacsSdk7FontDriver.java | |||
| @@ -243,93 +243,6 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver | |||
| 243 | } | 243 | } |
| 244 | }; | 244 | }; |
| 245 | 245 | ||
| 246 | private class Sdk7DrawString implements EmacsPaintReq | ||
| 247 | { | ||
| 248 | private boolean drawBackground; | ||
| 249 | private Sdk7FontObject fontObject; | ||
| 250 | private char[] chars; | ||
| 251 | private EmacsGC immutableGC; | ||
| 252 | private EmacsDrawable drawable; | ||
| 253 | private Rect rect; | ||
| 254 | private int originX, originY; | ||
| 255 | |||
| 256 | public | ||
| 257 | Sdk7DrawString (Sdk7FontObject fontObject, char[] chars, | ||
| 258 | EmacsGC immutableGC, EmacsDrawable drawable, | ||
| 259 | boolean drawBackground, Rect rect, | ||
| 260 | int originX, int originY) | ||
| 261 | { | ||
| 262 | this.fontObject = fontObject; | ||
| 263 | this.chars = chars; | ||
| 264 | this.immutableGC = immutableGC; | ||
| 265 | this.drawable = drawable; | ||
| 266 | this.drawBackground = drawBackground; | ||
| 267 | this.rect = rect; | ||
| 268 | this.originX = originX; | ||
| 269 | this.originY = originY; | ||
| 270 | } | ||
| 271 | |||
| 272 | @Override | ||
| 273 | public EmacsDrawable | ||
| 274 | getDrawable () | ||
| 275 | { | ||
| 276 | return drawable; | ||
| 277 | } | ||
| 278 | |||
| 279 | @Override | ||
| 280 | public EmacsGC | ||
| 281 | getGC () | ||
| 282 | { | ||
| 283 | return immutableGC; | ||
| 284 | } | ||
| 285 | |||
| 286 | @Override | ||
| 287 | public void | ||
| 288 | paintTo (Canvas canvas, Paint paint, EmacsGC immutableGC) | ||
| 289 | { | ||
| 290 | int scratch; | ||
| 291 | |||
| 292 | paint.setStyle (Paint.Style.FILL); | ||
| 293 | |||
| 294 | if (drawBackground) | ||
| 295 | { | ||
| 296 | paint.setColor (immutableGC.background | 0xff000000); | ||
| 297 | canvas.drawRect (rect, paint); | ||
| 298 | } | ||
| 299 | |||
| 300 | paint.setTextSize (fontObject.pixelSize); | ||
| 301 | paint.setColor (immutableGC.foreground | 0xff000000); | ||
| 302 | paint.setTypeface (fontObject.typeface.typeface); | ||
| 303 | paint.setAntiAlias (true); | ||
| 304 | |||
| 305 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) | ||
| 306 | /* Disable hinting as that leads to displayed text not | ||
| 307 | matching the computed metrics. */ | ||
| 308 | paint.setHinting (Paint.HINTING_OFF); | ||
| 309 | |||
| 310 | canvas.drawText (chars, 0, chars.length, originX, originY, paint); | ||
| 311 | paint.setAntiAlias (false); | ||
| 312 | } | ||
| 313 | |||
| 314 | @Override | ||
| 315 | public Rect | ||
| 316 | getRect () | ||
| 317 | { | ||
| 318 | Rect rect; | ||
| 319 | |||
| 320 | rect = new Rect (); | ||
| 321 | |||
| 322 | fontObject.typeface.typefacePaint.setTextSize (fontObject.pixelSize); | ||
| 323 | fontObject.typeface.typefacePaint.getTextBounds (chars, 0, chars.length, | ||
| 324 | rect); | ||
| 325 | |||
| 326 | /* Add the background rect to the damage as well. */ | ||
| 327 | rect.union (this.rect); | ||
| 328 | |||
| 329 | return rect; | ||
| 330 | } | ||
| 331 | }; | ||
| 332 | |||
| 333 | private String[] fontFamilyList; | 246 | private String[] fontFamilyList; |
| 334 | private Sdk7Typeface[] typefaceList; | 247 | private Sdk7Typeface[] typefaceList; |
| 335 | private Sdk7Typeface fallbackTypeface; | 248 | private Sdk7Typeface fallbackTypeface; |
| @@ -498,14 +411,11 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver | |||
| 498 | Paint paint, Rect bounds) | 411 | Paint paint, Rect bounds) |
| 499 | { | 412 | { |
| 500 | char[] text; | 413 | char[] text; |
| 501 | float[] width; | ||
| 502 | 414 | ||
| 503 | text = new char[1]; | 415 | text = new char[1]; |
| 504 | text[0] = (char) code; | 416 | text[0] = (char) code; |
| 505 | 417 | ||
| 506 | paint.getTextBounds (text, 0, 1, bounds); | 418 | paint.getTextBounds (text, 0, 1, bounds); |
| 507 | width = new float[1]; | ||
| 508 | paint.getTextWidths (text, 0, 1, width); | ||
| 509 | 419 | ||
| 510 | /* bounds is the bounding box of the glyph corresponding to CODE. | 420 | /* bounds is the bounding box of the glyph corresponding to CODE. |
| 511 | Translate these into XCharStruct values. | 421 | Translate these into XCharStruct values. |
| @@ -526,7 +436,7 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver | |||
| 526 | metrics.rbearing = (short) bounds.right; | 436 | metrics.rbearing = (short) bounds.right; |
| 527 | metrics.ascent = (short) -bounds.top; | 437 | metrics.ascent = (short) -bounds.top; |
| 528 | metrics.descent = (short) bounds.bottom; | 438 | metrics.descent = (short) bounds.bottom; |
| 529 | metrics.width = (short) Math.round (width[0]); | 439 | metrics.width = (short) paint.measureText ("" + text[0]); |
| 530 | } | 440 | } |
| 531 | 441 | ||
| 532 | @Override | 442 | @Override |
| @@ -563,7 +473,8 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver | |||
| 563 | for (i = 0; i < code.length; ++i) | 473 | for (i = 0; i < code.length; ++i) |
| 564 | text[i] = (char) code[i]; | 474 | text[i] = (char) code[i]; |
| 565 | 475 | ||
| 566 | paintCache.getTextBounds (text, 0, 1, boundsCache); | 476 | paintCache.getTextBounds (text, 0, code.length, |
| 477 | boundsCache); | ||
| 567 | width = paintCache.measureText (text, 0, code.length); | 478 | width = paintCache.measureText (text, 0, code.length); |
| 568 | 479 | ||
| 569 | fontMetrics.lbearing = (short) boundsCache.left; | 480 | fontMetrics.lbearing = (short) boundsCache.left; |
| @@ -587,11 +498,12 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver | |||
| 587 | int[] chars, int x, int y, int backgroundWidth, | 498 | int[] chars, int x, int y, int backgroundWidth, |
| 588 | boolean withBackground) | 499 | boolean withBackground) |
| 589 | { | 500 | { |
| 590 | Rect backgroundRect; | 501 | Rect backgroundRect, bounds; |
| 591 | Sdk7FontObject sdk7FontObject; | 502 | Sdk7FontObject sdk7FontObject; |
| 592 | Sdk7DrawString op; | ||
| 593 | char[] charsArray; | 503 | char[] charsArray; |
| 594 | int i; | 504 | int i; |
| 505 | Canvas canvas; | ||
| 506 | Paint paint; | ||
| 595 | 507 | ||
| 596 | sdk7FontObject = (Sdk7FontObject) fontObject; | 508 | sdk7FontObject = (Sdk7FontObject) fontObject; |
| 597 | charsArray = new char[chars.length]; | 509 | charsArray = new char[chars.length]; |
| @@ -605,12 +517,41 @@ public class EmacsSdk7FontDriver extends EmacsFontDriver | |||
| 605 | backgroundRect.right = x + backgroundWidth; | 517 | backgroundRect.right = x + backgroundWidth; |
| 606 | backgroundRect.bottom = y + sdk7FontObject.descent; | 518 | backgroundRect.bottom = y + sdk7FontObject.descent; |
| 607 | 519 | ||
| 608 | op = new Sdk7DrawString (sdk7FontObject, charsArray, | 520 | canvas = drawable.lockCanvas (); |
| 609 | gc.immutableGC (), drawable, | 521 | |
| 610 | withBackground, | 522 | if (canvas == null) |
| 611 | backgroundRect, x, y); | 523 | return 0; |
| 524 | |||
| 525 | canvas.save (); | ||
| 526 | paint = gc.gcPaint; | ||
| 527 | |||
| 528 | if (gc.real_clip_rects != null) | ||
| 529 | { | ||
| 530 | for (i = 0; i < gc.real_clip_rects.length; ++i) | ||
| 531 | canvas.clipRect (gc.real_clip_rects[i]); | ||
| 532 | } | ||
| 533 | |||
| 534 | paint.setStyle (Paint.Style.FILL); | ||
| 535 | |||
| 536 | if (withBackground) | ||
| 537 | { | ||
| 538 | paint.setColor (gc.background | 0xff000000); | ||
| 539 | canvas.drawRect (backgroundRect, paint); | ||
| 540 | paint.setColor (gc.foreground | 0xff000000); | ||
| 541 | } | ||
| 612 | 542 | ||
| 613 | EmacsService.SERVICE.appendPaintOperation (op); | 543 | paint.setTextSize (sdk7FontObject.pixelSize); |
| 544 | paint.setTypeface (sdk7FontObject.typeface.typeface); | ||
| 545 | paint.setAntiAlias (true); | ||
| 546 | canvas.drawText (charsArray, 0, chars.length, x, y, paint); | ||
| 547 | |||
| 548 | canvas.restore (); | ||
| 549 | bounds = new Rect (); | ||
| 550 | paint.getTextBounds (charsArray, 0, chars.length, bounds); | ||
| 551 | bounds.offset (x, y); | ||
| 552 | bounds.union (backgroundRect); | ||
| 553 | drawable.damageRect (bounds); | ||
| 554 | paint.setAntiAlias (false); | ||
| 614 | return 1; | 555 | return 1; |
| 615 | } | 556 | } |
| 616 | }; | 557 | }; |
diff --git a/java/org/gnu/emacs/EmacsService.java b/java/org/gnu/emacs/EmacsService.java index 41a45b0bd85..4444b7f1c56 100644 --- a/java/org/gnu/emacs/EmacsService.java +++ b/java/org/gnu/emacs/EmacsService.java | |||
| @@ -19,7 +19,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 19 | 19 | ||
| 20 | package org.gnu.emacs; | 20 | package org.gnu.emacs; |
| 21 | 21 | ||
| 22 | import java.lang.Runnable; | ||
| 23 | import java.io.IOException; | 22 | import java.io.IOException; |
| 24 | import java.util.List; | 23 | import java.util.List; |
| 25 | import java.util.ArrayList; | 24 | import java.util.ArrayList; |
| @@ -59,7 +58,6 @@ public class EmacsService extends Service | |||
| 59 | 58 | ||
| 60 | private EmacsThread thread; | 59 | private EmacsThread thread; |
| 61 | private Handler handler; | 60 | private Handler handler; |
| 62 | private EmacsPaintQueue paintQueue; | ||
| 63 | 61 | ||
| 64 | /* Display metrics used by font backends. */ | 62 | /* Display metrics used by font backends. */ |
| 65 | public DisplayMetrics metrics; | 63 | public DisplayMetrics metrics; |
| @@ -191,126 +189,42 @@ public class EmacsService extends Service | |||
| 191 | return view.thing; | 189 | return view.thing; |
| 192 | } | 190 | } |
| 193 | 191 | ||
| 194 | /* X drawing operations. These are quite primitive operations. The | ||
| 195 | drawing queue is kept on the Emacs thread, but is periodically | ||
| 196 | flushed to the application thread, upon buffers swaps and once it | ||
| 197 | gets too big. */ | ||
| 198 | |||
| 199 | |||
| 200 | |||
| 201 | private void | ||
| 202 | ensurePaintQueue () | ||
| 203 | { | ||
| 204 | if (paintQueue == null) | ||
| 205 | paintQueue = new EmacsPaintQueue (); | ||
| 206 | } | ||
| 207 | |||
| 208 | public void | ||
| 209 | flushPaintQueue () | ||
| 210 | { | ||
| 211 | final EmacsPaintQueue queue; | ||
| 212 | |||
| 213 | if (paintQueue == null) | ||
| 214 | return; | ||
| 215 | |||
| 216 | if (paintQueue.numRequests < 1) | ||
| 217 | /* No requests to flush. */ | ||
| 218 | return; | ||
| 219 | |||
| 220 | queue = paintQueue; | ||
| 221 | |||
| 222 | handler.post (new Runnable () { | ||
| 223 | @Override | ||
| 224 | public void | ||
| 225 | run () | ||
| 226 | { | ||
| 227 | queue.run (); | ||
| 228 | } | ||
| 229 | }); | ||
| 230 | |||
| 231 | /* Clear the paint queue. */ | ||
| 232 | paintQueue = null; | ||
| 233 | } | ||
| 234 | |||
| 235 | private void | ||
| 236 | checkFlush () | ||
| 237 | { | ||
| 238 | if (paintQueue != null | ||
| 239 | && paintQueue.numRequests > MAX_PENDING_REQUESTS) | ||
| 240 | flushPaintQueue (); | ||
| 241 | } | ||
| 242 | |||
| 243 | public void | 192 | public void |
| 244 | fillRectangle (EmacsDrawable drawable, EmacsGC gc, | 193 | fillRectangle (EmacsDrawable drawable, EmacsGC gc, |
| 245 | int x, int y, int width, int height) | 194 | int x, int y, int width, int height) |
| 246 | { | 195 | { |
| 247 | EmacsPaintReq req; | 196 | EmacsFillRectangle.perform (drawable, gc, x, y, |
| 248 | 197 | width, height); | |
| 249 | ensurePaintQueue (); | ||
| 250 | |||
| 251 | req = new EmacsFillRectangle (drawable, x, y, | ||
| 252 | width, height, | ||
| 253 | gc.immutableGC ()); | ||
| 254 | paintQueue.appendPaintOperation (req); | ||
| 255 | checkFlush (); | ||
| 256 | } | 198 | } |
| 257 | 199 | ||
| 258 | public void | 200 | public void |
| 259 | fillPolygon (EmacsDrawable drawable, EmacsGC gc, | 201 | fillPolygon (EmacsDrawable drawable, EmacsGC gc, |
| 260 | Point points[]) | 202 | Point points[]) |
| 261 | { | 203 | { |
| 262 | EmacsPaintReq req; | 204 | EmacsFillPolygon.perform (drawable, gc, points); |
| 263 | |||
| 264 | ensurePaintQueue (); | ||
| 265 | |||
| 266 | req = new EmacsFillPolygon (drawable, points, | ||
| 267 | gc.immutableGC ()); | ||
| 268 | paintQueue.appendPaintOperation (req); | ||
| 269 | checkFlush (); | ||
| 270 | } | 205 | } |
| 271 | 206 | ||
| 272 | public void | 207 | public void |
| 273 | drawRectangle (EmacsDrawable drawable, EmacsGC gc, | 208 | drawRectangle (EmacsDrawable drawable, EmacsGC gc, |
| 274 | int x, int y, int width, int height) | 209 | int x, int y, int width, int height) |
| 275 | { | 210 | { |
| 276 | EmacsPaintReq req; | 211 | EmacsDrawRectangle.perform (drawable, gc, x, y, |
| 277 | 212 | width, height); | |
| 278 | ensurePaintQueue (); | ||
| 279 | |||
| 280 | req = new EmacsDrawRectangle (drawable, x, y, | ||
| 281 | width, height, | ||
| 282 | gc.immutableGC ()); | ||
| 283 | paintQueue.appendPaintOperation (req); | ||
| 284 | checkFlush (); | ||
| 285 | } | 213 | } |
| 286 | 214 | ||
| 287 | public void | 215 | public void |
| 288 | drawLine (EmacsDrawable drawable, EmacsGC gc, | 216 | drawLine (EmacsDrawable drawable, EmacsGC gc, |
| 289 | int x, int y, int x2, int y2) | 217 | int x, int y, int x2, int y2) |
| 290 | { | 218 | { |
| 291 | EmacsPaintReq req; | 219 | EmacsDrawLine.perform (drawable, gc, x, y, |
| 292 | 220 | x2, y2); | |
| 293 | ensurePaintQueue (); | ||
| 294 | |||
| 295 | req = new EmacsDrawLine (drawable, x, y, | ||
| 296 | x2, y2, | ||
| 297 | gc.immutableGC ()); | ||
| 298 | paintQueue.appendPaintOperation (req); | ||
| 299 | checkFlush (); | ||
| 300 | } | 221 | } |
| 301 | 222 | ||
| 302 | public void | 223 | public void |
| 303 | drawPoint (EmacsDrawable drawable, EmacsGC gc, | 224 | drawPoint (EmacsDrawable drawable, EmacsGC gc, |
| 304 | int x, int y) | 225 | int x, int y) |
| 305 | { | 226 | { |
| 306 | EmacsPaintReq req; | 227 | EmacsDrawPoint.perform (drawable, gc, x, y); |
| 307 | |||
| 308 | ensurePaintQueue (); | ||
| 309 | |||
| 310 | req = new EmacsDrawPoint (drawable, x, y, | ||
| 311 | gc.immutableGC ()); | ||
| 312 | paintQueue.appendPaintOperation (req); | ||
| 313 | checkFlush (); | ||
| 314 | } | 228 | } |
| 315 | 229 | ||
| 316 | public void | 230 | public void |
| @@ -319,15 +233,9 @@ public class EmacsService extends Service | |||
| 319 | int srcX, int srcY, int width, int height, int destX, | 233 | int srcX, int srcY, int width, int height, int destX, |
| 320 | int destY) | 234 | int destY) |
| 321 | { | 235 | { |
| 322 | EmacsPaintReq req; | 236 | EmacsCopyArea.perform (srcDrawable, gc, dstDrawable, |
| 323 | 237 | srcX, srcY, width, height, destX, | |
| 324 | ensurePaintQueue (); | 238 | destY); |
| 325 | |||
| 326 | req = new EmacsCopyArea (srcDrawable, dstDrawable, | ||
| 327 | srcX, srcY, width, height, destX, | ||
| 328 | destY, gc.immutableGC ()); | ||
| 329 | paintQueue.appendPaintOperation (req); | ||
| 330 | checkFlush (); | ||
| 331 | } | 239 | } |
| 332 | 240 | ||
| 333 | public void | 241 | public void |
| @@ -342,12 +250,4 @@ public class EmacsService extends Service | |||
| 342 | { | 250 | { |
| 343 | window.clearArea (x, y, width, height); | 251 | window.clearArea (x, y, width, height); |
| 344 | } | 252 | } |
| 345 | |||
| 346 | public void | ||
| 347 | appendPaintOperation (EmacsPaintReq op) | ||
| 348 | { | ||
| 349 | ensurePaintQueue (); | ||
| 350 | paintQueue.appendPaintOperation (op); | ||
| 351 | checkFlush (); | ||
| 352 | } | ||
| 353 | }; | 253 | }; |
diff --git a/java/org/gnu/emacs/EmacsSurfaceView.java b/java/org/gnu/emacs/EmacsSurfaceView.java index b8b828e4820..5efb8882263 100644 --- a/java/org/gnu/emacs/EmacsSurfaceView.java +++ b/java/org/gnu/emacs/EmacsSurfaceView.java | |||
| @@ -29,6 +29,7 @@ import android.graphics.Rect; | |||
| 29 | 29 | ||
| 30 | public class EmacsSurfaceView extends SurfaceView | 30 | public class EmacsSurfaceView extends SurfaceView |
| 31 | { | 31 | { |
| 32 | public Object surfaceChangeLock; | ||
| 32 | private boolean created; | 33 | private boolean created; |
| 33 | 34 | ||
| 34 | public | 35 | public |
| @@ -36,33 +37,36 @@ public class EmacsSurfaceView extends SurfaceView | |||
| 36 | { | 37 | { |
| 37 | super (view.getContext ()); | 38 | super (view.getContext ()); |
| 38 | 39 | ||
| 40 | surfaceChangeLock = new Object (); | ||
| 41 | |||
| 39 | getHolder ().addCallback (new SurfaceHolder.Callback () { | 42 | getHolder ().addCallback (new SurfaceHolder.Callback () { |
| 40 | @Override | 43 | @Override |
| 41 | public void | 44 | public void |
| 42 | surfaceChanged (SurfaceHolder holder, int format, | 45 | surfaceChanged (SurfaceHolder holder, int format, |
| 43 | int width, int height) | 46 | int width, int height) |
| 44 | { | 47 | { |
| 45 | /* Force a buffer swap now to get the contents of the Emacs | 48 | view.swapBuffers (); |
| 46 | view on screen. */ | ||
| 47 | view.swapBuffers (true); | ||
| 48 | } | 49 | } |
| 49 | 50 | ||
| 50 | @Override | 51 | @Override |
| 51 | public void | 52 | public void |
| 52 | surfaceCreated (SurfaceHolder holder) | 53 | surfaceCreated (SurfaceHolder holder) |
| 53 | { | 54 | { |
| 54 | created = true; | 55 | synchronized (surfaceChangeLock) |
| 55 | 56 | { | |
| 56 | /* Force a buffer swap now to get the contents of the Emacs | 57 | created = true; |
| 57 | view on screen. */ | 58 | view.swapBuffers (); |
| 58 | view.swapBuffers (true); | 59 | } |
| 59 | } | 60 | } |
| 60 | 61 | ||
| 61 | @Override | 62 | @Override |
| 62 | public void | 63 | public void |
| 63 | surfaceDestroyed (SurfaceHolder holder) | 64 | surfaceDestroyed (SurfaceHolder holder) |
| 64 | { | 65 | { |
| 65 | created = false; | 66 | synchronized (surfaceChangeLock) |
| 67 | { | ||
| 68 | created = false; | ||
| 69 | } | ||
| 66 | } | 70 | } |
| 67 | }); | 71 | }); |
| 68 | } | 72 | } |
diff --git a/java/org/gnu/emacs/EmacsView.java b/java/org/gnu/emacs/EmacsView.java index 7b48eaf0aa6..169a1e42ee3 100644 --- a/java/org/gnu/emacs/EmacsView.java +++ b/java/org/gnu/emacs/EmacsView.java | |||
| @@ -23,6 +23,7 @@ import android.content.res.ColorStateList; | |||
| 23 | 23 | ||
| 24 | import android.view.View; | 24 | import android.view.View; |
| 25 | import android.view.KeyEvent; | 25 | import android.view.KeyEvent; |
| 26 | import android.view.MotionEvent; | ||
| 26 | import android.view.ViewGroup; | 27 | import android.view.ViewGroup; |
| 27 | 28 | ||
| 28 | import android.graphics.Bitmap; | 29 | import android.graphics.Bitmap; |
| @@ -64,6 +65,14 @@ public class EmacsView extends ViewGroup | |||
| 64 | /* The associated surface view. */ | 65 | /* The associated surface view. */ |
| 65 | private EmacsSurfaceView surfaceView; | 66 | private EmacsSurfaceView surfaceView; |
| 66 | 67 | ||
| 68 | /* Whether or not a configure event must be sent for the next layout | ||
| 69 | event regardless of what changed. */ | ||
| 70 | public boolean mustReportLayout; | ||
| 71 | |||
| 72 | /* If non-null, whether or not bitmaps must be recreated upon the | ||
| 73 | next call to getBitmap. */ | ||
| 74 | private Rect bitmapDirty; | ||
| 75 | |||
| 67 | public | 76 | public |
| 68 | EmacsView (EmacsWindow window) | 77 | EmacsView (EmacsWindow window) |
| 69 | { | 78 | { |
| @@ -81,6 +90,43 @@ public class EmacsView extends ViewGroup | |||
| 81 | addView (this.surfaceView); | 90 | addView (this.surfaceView); |
| 82 | } | 91 | } |
| 83 | 92 | ||
| 93 | private void | ||
| 94 | handleDirtyBitmap () | ||
| 95 | { | ||
| 96 | /* Recreate the front and back buffer bitmaps. */ | ||
| 97 | bitmap | ||
| 98 | = Bitmap.createBitmap (bitmapDirty.width (), | ||
| 99 | bitmapDirty.height (), | ||
| 100 | Bitmap.Config.ARGB_8888); | ||
| 101 | bitmap.eraseColor (0xffffffff); | ||
| 102 | |||
| 103 | /* And canvases. */ | ||
| 104 | canvas = new Canvas (bitmap); | ||
| 105 | |||
| 106 | /* If Emacs is drawing to the bitmap right now from the | ||
| 107 | main thread, the image contents are lost until the next | ||
| 108 | ConfigureNotify and complete garbage. Sorry! */ | ||
| 109 | bitmapDirty = null; | ||
| 110 | } | ||
| 111 | |||
| 112 | public synchronized Bitmap | ||
| 113 | getBitmap () | ||
| 114 | { | ||
| 115 | if (bitmapDirty != null) | ||
| 116 | handleDirtyBitmap (); | ||
| 117 | |||
| 118 | return bitmap; | ||
| 119 | } | ||
| 120 | |||
| 121 | public synchronized Canvas | ||
| 122 | getCanvas () | ||
| 123 | { | ||
| 124 | if (bitmapDirty != null) | ||
| 125 | handleDirtyBitmap (); | ||
| 126 | |||
| 127 | return canvas; | ||
| 128 | } | ||
| 129 | |||
| 84 | @Override | 130 | @Override |
| 85 | protected void | 131 | protected void |
| 86 | onMeasure (int widthMeasureSpec, int heightMeasureSpec) | 132 | onMeasure (int widthMeasureSpec, int heightMeasureSpec) |
| @@ -114,7 +160,7 @@ public class EmacsView extends ViewGroup | |||
| 114 | } | 160 | } |
| 115 | 161 | ||
| 116 | @Override | 162 | @Override |
| 117 | protected void | 163 | protected synchronized void |
| 118 | onLayout (boolean changed, int left, int top, int right, | 164 | onLayout (boolean changed, int left, int top, int right, |
| 119 | int bottom) | 165 | int bottom) |
| 120 | { | 166 | { |
| @@ -122,19 +168,15 @@ public class EmacsView extends ViewGroup | |||
| 122 | View child; | 168 | View child; |
| 123 | Rect windowRect; | 169 | Rect windowRect; |
| 124 | 170 | ||
| 125 | if (changed) | 171 | if (changed || mustReportLayout) |
| 126 | { | 172 | { |
| 173 | mustReportLayout = false; | ||
| 127 | window.viewLayout (left, top, right, bottom); | 174 | window.viewLayout (left, top, right, bottom); |
| 128 | |||
| 129 | /* Recreate the front and back buffer bitmaps. */ | ||
| 130 | bitmap | ||
| 131 | = Bitmap.createBitmap (right - left, bottom - top, | ||
| 132 | Bitmap.Config.ARGB_8888); | ||
| 133 | |||
| 134 | /* And canvases. */ | ||
| 135 | canvas = new Canvas (bitmap); | ||
| 136 | } | 175 | } |
| 137 | 176 | ||
| 177 | if (changed) | ||
| 178 | bitmapDirty = new Rect (left, top, right, bottom); | ||
| 179 | |||
| 138 | count = getChildCount (); | 180 | count = getChildCount (); |
| 139 | 181 | ||
| 140 | for (i = 0; i < count; ++i) | 182 | for (i = 0; i < count; ++i) |
| @@ -159,47 +201,60 @@ public class EmacsView extends ViewGroup | |||
| 159 | } | 201 | } |
| 160 | } | 202 | } |
| 161 | 203 | ||
| 162 | public void | 204 | public synchronized void |
| 163 | damageRect (Rect damageRect) | 205 | damageRect (Rect damageRect) |
| 164 | { | 206 | { |
| 165 | damageRegion.union (damageRect); | 207 | damageRegion.union (damageRect); |
| 166 | } | 208 | } |
| 167 | 209 | ||
| 168 | public void | 210 | /* This method is called from both the UI thread and the Emacs |
| 211 | thread. */ | ||
| 212 | |||
| 213 | public synchronized void | ||
| 169 | swapBuffers (boolean force) | 214 | swapBuffers (boolean force) |
| 170 | { | 215 | { |
| 171 | Bitmap back; | ||
| 172 | Canvas canvas; | 216 | Canvas canvas; |
| 173 | Rect damageRect; | 217 | Rect damageRect; |
| 218 | Bitmap bitmap; | ||
| 174 | 219 | ||
| 175 | if (damageRegion.isEmpty ()) | 220 | if (damageRegion.isEmpty ()) |
| 176 | return; | 221 | return; |
| 177 | 222 | ||
| 178 | if (!surfaceView.isCreated ()) | 223 | bitmap = getBitmap (); |
| 179 | return; | ||
| 180 | 224 | ||
| 181 | if (bitmap == null) | 225 | /* Emacs must take the following lock to ensure the access to the |
| 182 | return; | 226 | canvas occurs with the surface created. Otherwise, Android |
| 227 | will throttle calls to lockCanvas. */ | ||
| 228 | |||
| 229 | synchronized (surfaceView.surfaceChangeLock) | ||
| 230 | { | ||
| 231 | damageRect = damageRegion.getBounds (); | ||
| 183 | 232 | ||
| 184 | /* Lock the canvas with the specified damage. */ | 233 | if (!surfaceView.isCreated ()) |
| 185 | damageRect = damageRegion.getBounds (); | 234 | return; |
| 186 | canvas = surfaceView.lockCanvas (damageRect); | ||
| 187 | 235 | ||
| 188 | /* Return if locking the canvas failed. */ | 236 | if (bitmap == null) |
| 189 | if (canvas == null) | 237 | return; |
| 190 | return; | 238 | |
| 239 | /* Lock the canvas with the specified damage. */ | ||
| 240 | canvas = surfaceView.lockCanvas (damageRect); | ||
| 191 | 241 | ||
| 192 | /* Copy from the back buffer to the canvas. If damageRect was | 242 | /* Return if locking the canvas failed. */ |
| 193 | made empty, then draw the entire back buffer. */ | 243 | if (canvas == null) |
| 244 | return; | ||
| 194 | 245 | ||
| 195 | if (damageRect.isEmpty ()) | 246 | /* Copy from the back buffer to the canvas. If damageRect was |
| 196 | canvas.drawBitmap (bitmap, 0f, 0f, paint); | 247 | made empty, then draw the entire back buffer. */ |
| 197 | else | ||
| 198 | canvas.drawBitmap (bitmap, damageRect, damageRect, paint); | ||
| 199 | 248 | ||
| 200 | /* Unlock the canvas and clear the damage. */ | 249 | if (damageRect.isEmpty ()) |
| 201 | surfaceView.unlockCanvasAndPost (canvas); | 250 | canvas.drawBitmap (bitmap, 0f, 0f, paint); |
| 202 | damageRegion.setEmpty (); | 251 | else |
| 252 | canvas.drawBitmap (bitmap, damageRect, damageRect, paint); | ||
| 253 | |||
| 254 | /* Unlock the canvas and clear the damage. */ | ||
| 255 | surfaceView.unlockCanvasAndPost (canvas); | ||
| 256 | damageRegion.setEmpty (); | ||
| 257 | } | ||
| 203 | } | 258 | } |
| 204 | 259 | ||
| 205 | public void | 260 | public void |
| @@ -241,4 +296,18 @@ public class EmacsView extends ViewGroup | |||
| 241 | super.onFocusChanged (gainFocus, direction, | 296 | super.onFocusChanged (gainFocus, direction, |
| 242 | previouslyFocusedRect); | 297 | previouslyFocusedRect); |
| 243 | } | 298 | } |
| 299 | |||
| 300 | @Override | ||
| 301 | public boolean | ||
| 302 | onGenericMotionEvent (MotionEvent motion) | ||
| 303 | { | ||
| 304 | return window.onSomeKindOfMotionEvent (motion); | ||
| 305 | } | ||
| 306 | |||
| 307 | @Override | ||
| 308 | public boolean | ||
| 309 | onTouchEvent (MotionEvent motion) | ||
| 310 | { | ||
| 311 | return window.onSomeKindOfMotionEvent (motion); | ||
| 312 | } | ||
| 244 | }; | 313 | }; |
diff --git a/java/org/gnu/emacs/EmacsWindow.java b/java/org/gnu/emacs/EmacsWindow.java index 26e788a20a8..a9a24b61869 100644 --- a/java/org/gnu/emacs/EmacsWindow.java +++ b/java/org/gnu/emacs/EmacsWindow.java | |||
| @@ -31,8 +31,13 @@ import android.graphics.Point; | |||
| 31 | import android.view.View; | 31 | import android.view.View; |
| 32 | import android.view.ViewGroup; | 32 | import android.view.ViewGroup; |
| 33 | import android.view.KeyEvent; | 33 | import android.view.KeyEvent; |
| 34 | import android.view.MotionEvent; | ||
| 35 | import android.view.InputDevice; | ||
| 34 | 36 | ||
| 35 | import android.content.Intent; | 37 | import android.content.Intent; |
| 38 | import android.util.Log; | ||
| 39 | |||
| 40 | import android.os.Build; | ||
| 36 | 41 | ||
| 37 | /* This defines a window, which is a handle. Windows represent a | 42 | /* This defines a window, which is a handle. Windows represent a |
| 38 | rectangular subset of the screen with their own contents. | 43 | rectangular subset of the screen with their own contents. |
| @@ -68,6 +73,10 @@ public class EmacsWindow extends EmacsHandleObject | |||
| 68 | window background. */ | 73 | window background. */ |
| 69 | private EmacsGC scratchGC; | 74 | private EmacsGC scratchGC; |
| 70 | 75 | ||
| 76 | /* The button state and keyboard modifier mask at the time of the | ||
| 77 | last button press or release event. */ | ||
| 78 | private int lastButtonState, lastModifiers; | ||
| 79 | |||
| 71 | public | 80 | public |
| 72 | EmacsWindow (short handle, final EmacsWindow parent, int x, int y, | 81 | EmacsWindow (short handle, final EmacsWindow parent, int x, int y, |
| 73 | int width, int height) | 82 | int width, int height) |
| @@ -212,6 +221,7 @@ public class EmacsWindow extends EmacsHandleObject | |||
| 212 | public void | 221 | public void |
| 213 | run () | 222 | run () |
| 214 | { | 223 | { |
| 224 | view.mustReportLayout = true; | ||
| 215 | view.requestLayout (); | 225 | view.requestLayout (); |
| 216 | } | 226 | } |
| 217 | }); | 227 | }); |
| @@ -224,6 +234,8 @@ public class EmacsWindow extends EmacsHandleObject | |||
| 224 | { | 234 | { |
| 225 | rect.right = rect.left + width; | 235 | rect.right = rect.left + width; |
| 226 | rect.bottom = rect.top + height; | 236 | rect.bottom = rect.top + height; |
| 237 | |||
| 238 | requestViewLayout (); | ||
| 227 | } | 239 | } |
| 228 | } | 240 | } |
| 229 | 241 | ||
| @@ -279,17 +291,7 @@ public class EmacsWindow extends EmacsHandleObject | |||
| 279 | public Canvas | 291 | public Canvas |
| 280 | lockCanvas () | 292 | lockCanvas () |
| 281 | { | 293 | { |
| 282 | if (view.canvas != null) | 294 | return view.getCanvas (); |
| 283 | return view.canvas; | ||
| 284 | |||
| 285 | return null; | ||
| 286 | } | ||
| 287 | |||
| 288 | @Override | ||
| 289 | public void | ||
| 290 | unlockCanvas () | ||
| 291 | { | ||
| 292 | |||
| 293 | } | 295 | } |
| 294 | 296 | ||
| 295 | @Override | 297 | @Override |
| @@ -302,17 +304,7 @@ public class EmacsWindow extends EmacsHandleObject | |||
| 302 | public void | 304 | public void |
| 303 | swapBuffers () | 305 | swapBuffers () |
| 304 | { | 306 | { |
| 305 | /* Before calling swapBuffers, make sure to flush the paint | 307 | view.swapBuffers (); |
| 306 | queue. */ | ||
| 307 | EmacsService.SERVICE.flushPaintQueue (); | ||
| 308 | view.post (new Runnable () { | ||
| 309 | @Override | ||
| 310 | public void | ||
| 311 | run () | ||
| 312 | { | ||
| 313 | view.swapBuffers (); | ||
| 314 | } | ||
| 315 | }); | ||
| 316 | } | 308 | } |
| 317 | 309 | ||
| 318 | public void | 310 | public void |
| @@ -337,7 +329,7 @@ public class EmacsWindow extends EmacsHandleObject | |||
| 337 | public Bitmap | 329 | public Bitmap |
| 338 | getBitmap () | 330 | getBitmap () |
| 339 | { | 331 | { |
| 340 | return view.bitmap; | 332 | return view.getBitmap (); |
| 341 | } | 333 | } |
| 342 | 334 | ||
| 343 | public void | 335 | public void |
| @@ -357,6 +349,7 @@ public class EmacsWindow extends EmacsHandleObject | |||
| 357 | recognized as an ASCII key press | 349 | recognized as an ASCII key press |
| 358 | event. */ | 350 | event. */ |
| 359 | event.getUnicodeChar (state)); | 351 | event.getUnicodeChar (state)); |
| 352 | lastModifiers = event.getModifiers (); | ||
| 360 | } | 353 | } |
| 361 | 354 | ||
| 362 | public void | 355 | public void |
| @@ -372,6 +365,7 @@ public class EmacsWindow extends EmacsHandleObject | |||
| 372 | event.getModifiers (), | 365 | event.getModifiers (), |
| 373 | keyCode, | 366 | keyCode, |
| 374 | event.getUnicodeChar (state)); | 367 | event.getUnicodeChar (state)); |
| 368 | lastModifiers = event.getModifiers (); | ||
| 375 | } | 369 | } |
| 376 | 370 | ||
| 377 | public void | 371 | public void |
| @@ -386,4 +380,105 @@ public class EmacsWindow extends EmacsHandleObject | |||
| 386 | /* Destroy the associated frame when the activity is detached. */ | 380 | /* Destroy the associated frame when the activity is detached. */ |
| 387 | EmacsNative.sendWindowAction (this.handle, 0); | 381 | EmacsNative.sendWindowAction (this.handle, 0); |
| 388 | } | 382 | } |
| 383 | |||
| 384 | /* Look through the button state to determine what button EVENT was | ||
| 385 | generated from. DOWN is true if EVENT is a button press event, | ||
| 386 | false otherwise. Value is the X number of the button. */ | ||
| 387 | |||
| 388 | private int | ||
| 389 | whatButtonWasIt (MotionEvent event, boolean down) | ||
| 390 | { | ||
| 391 | int eventState, notIn; | ||
| 392 | |||
| 393 | if (Build.VERSION.SDK_INT | ||
| 394 | < Build.VERSION_CODES.ICE_CREAM_SANDWICH) | ||
| 395 | /* Earlier versions of Android only support one mouse | ||
| 396 | button. */ | ||
| 397 | return 1; | ||
| 398 | |||
| 399 | eventState = event.getButtonState (); | ||
| 400 | notIn = (down ? eventState & ~lastButtonState | ||
| 401 | : lastButtonState & ~eventState); | ||
| 402 | |||
| 403 | if ((notIn & MotionEvent.BUTTON_PRIMARY) != 0) | ||
| 404 | return 1; | ||
| 405 | |||
| 406 | if ((notIn & MotionEvent.BUTTON_SECONDARY) != 0) | ||
| 407 | return 3; | ||
| 408 | |||
| 409 | if ((notIn & MotionEvent.BUTTON_TERTIARY) != 0) | ||
| 410 | return 2; | ||
| 411 | |||
| 412 | /* Not a real value. */ | ||
| 413 | return 4; | ||
| 414 | } | ||
| 415 | |||
| 416 | public boolean | ||
| 417 | onSomeKindOfMotionEvent (MotionEvent event) | ||
| 418 | { | ||
| 419 | if (!event.isFromSource (InputDevice.SOURCE_CLASS_POINTER)) | ||
| 420 | return false; | ||
| 421 | |||
| 422 | switch (event.getAction ()) | ||
| 423 | { | ||
| 424 | case MotionEvent.ACTION_HOVER_ENTER: | ||
| 425 | EmacsNative.sendEnterNotify (this.handle, (int) event.getX (), | ||
| 426 | (int) event.getY (), | ||
| 427 | event.getEventTime ()); | ||
| 428 | return true; | ||
| 429 | |||
| 430 | case MotionEvent.ACTION_MOVE: | ||
| 431 | case MotionEvent.ACTION_HOVER_MOVE: | ||
| 432 | EmacsNative.sendMotionNotify (this.handle, (int) event.getX (), | ||
| 433 | (int) event.getY (), | ||
| 434 | event.getEventTime ()); | ||
| 435 | return true; | ||
| 436 | |||
| 437 | case MotionEvent.ACTION_HOVER_EXIT: | ||
| 438 | EmacsNative.sendLeaveNotify (this.handle, (int) event.getX (), | ||
| 439 | (int) event.getY (), | ||
| 440 | event.getEventTime ()); | ||
| 441 | return true; | ||
| 442 | |||
| 443 | case MotionEvent.ACTION_BUTTON_PRESS: | ||
| 444 | /* Find the button which was pressed. */ | ||
| 445 | EmacsNative.sendButtonPress (this.handle, (int) event.getX (), | ||
| 446 | (int) event.getY (), | ||
| 447 | event.getEventTime (), | ||
| 448 | lastModifiers, | ||
| 449 | whatButtonWasIt (event, true)); | ||
| 450 | |||
| 451 | if (Build.VERSION.SDK_INT | ||
| 452 | < Build.VERSION_CODES.ICE_CREAM_SANDWICH) | ||
| 453 | return true; | ||
| 454 | |||
| 455 | lastButtonState = event.getButtonState (); | ||
| 456 | return true; | ||
| 457 | |||
| 458 | case MotionEvent.ACTION_BUTTON_RELEASE: | ||
| 459 | /* Find the button which was released. */ | ||
| 460 | EmacsNative.sendButtonRelease (this.handle, (int) event.getX (), | ||
| 461 | (int) event.getY (), | ||
| 462 | event.getEventTime (), | ||
| 463 | lastModifiers, | ||
| 464 | whatButtonWasIt (event, false)); | ||
| 465 | |||
| 466 | if (Build.VERSION.SDK_INT | ||
| 467 | < Build.VERSION_CODES.ICE_CREAM_SANDWICH) | ||
| 468 | return true; | ||
| 469 | |||
| 470 | lastButtonState = event.getButtonState (); | ||
| 471 | return true; | ||
| 472 | |||
| 473 | case MotionEvent.ACTION_DOWN: | ||
| 474 | case MotionEvent.ACTION_UP: | ||
| 475 | /* Emacs must return true even though touch events are not yet | ||
| 476 | handled, because the value of this function is used by the | ||
| 477 | system to decide whether or not Emacs gets ACTION_MOVE | ||
| 478 | events. */ | ||
| 479 | return true; | ||
| 480 | } | ||
| 481 | |||
| 482 | return false; | ||
| 483 | } | ||
| 389 | }; | 484 | }; |