diff options
| author | Po Lu | 2024-04-28 16:58:58 +0800 |
|---|---|---|
| committer | Po Lu | 2024-04-28 17:00:43 +0800 |
| commit | e658a6938e3b7a8a7c0be8b74fbd885787c26df6 (patch) | |
| tree | 9da9dec34bfd979ad7d09b4cdd6997ea0480f048 /java/org | |
| parent | b329358334712671de38f919c99d1434026aa8f2 (diff) | |
| download | emacs-e658a6938e3b7a8a7c0be8b74fbd885787c26df6.tar.gz emacs-e658a6938e3b7a8a7c0be8b74fbd885787c26df6.zip | |
Implement dots and dashes on Android
* java/org/gnu/emacs/EmacsDrawLine.java (EmacsDrawLine)
(measureLine, polyDashPattern): New function.
(perform): Delegate to polyDashPattern if the line style is not
LineSolid. Also simplify now that anti-aliasing need no longer
be taken into account.
* java/org/gnu/emacs/EmacsDrawRectangle.java (perform): Mention
omission in commentary.
* java/org/gnu/emacs/EmacsGC.java (EmacsGC): Disable
anti-aliasing in default paint object.
<line_style, line>: New fields.
(markDirty): Apply stroke width.
* src/android.c (android_init_emacs_gc_class): Initialize new
fields.
(android_create_gc, android_free_gc, android_change_gc)
(android_set_dashes, android_get_gc_values):
* src/androidgui.h (enum android_line_style)
(enum android_gc_value_mask, struct android_gc): Introduce line
style, width, dash offset and dash GC attributes.
* src/androidterm.c (android_draw_dash, android_fill_underline)
(android_draw_glyph_string): Port from X.
* src/xterm.c (x_draw_dash): Delete redundant code.
Diffstat (limited to 'java/org')
| -rw-r--r-- | java/org/gnu/emacs/EmacsDrawLine.java | 109 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsDrawRectangle.java | 3 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsGC.java | 12 |
3 files changed, 113 insertions, 11 deletions
diff --git a/java/org/gnu/emacs/EmacsDrawLine.java b/java/org/gnu/emacs/EmacsDrawLine.java index 61b7d54d63c..a49fe96c26e 100644 --- a/java/org/gnu/emacs/EmacsDrawLine.java +++ b/java/org/gnu/emacs/EmacsDrawLine.java | |||
| @@ -25,6 +25,97 @@ import android.graphics.Rect; | |||
| 25 | 25 | ||
| 26 | public final class EmacsDrawLine | 26 | public final class EmacsDrawLine |
| 27 | { | 27 | { |
| 28 | /* Return the normalized slope and magnitude of a line whose extrema | ||
| 29 | are DX and DY removed, on the X and Y axes respectively, from its | ||
| 30 | origin point. */ | ||
| 31 | |||
| 32 | private static float[] | ||
| 33 | measureLine (float dx, float dy) | ||
| 34 | { | ||
| 35 | float hypot; | ||
| 36 | |||
| 37 | if (dx == 0f && dy == 0f) | ||
| 38 | return new float[] { 0f, 0f, 0f, }; | ||
| 39 | |||
| 40 | if (dx == 0f) | ||
| 41 | return new float[] { 0f, dy > 0f ? 1f : -1f, Math.abs (dy), }; | ||
| 42 | else if (dy == 0f) | ||
| 43 | return new float[] { dx > 0f ? 1f : -1f, 0f, Math.abs (dx), }; | ||
| 44 | else | ||
| 45 | { | ||
| 46 | hypot = (float) Math.hypot (dx, dy); | ||
| 47 | return new float[] { dx / hypot, dy / hypot, hypot, }; | ||
| 48 | } | ||
| 49 | } | ||
| 50 | |||
| 51 | private static void | ||
| 52 | polyDashPattern (EmacsGC gc, Canvas canvas, Paint paint, float x0, | ||
| 53 | float y0, float x1, float y1) | ||
| 54 | { | ||
| 55 | int patternTotal, i, offset; | ||
| 56 | float dx, dy, mag, dash_mag, rem, lx1, ly1; | ||
| 57 | float[] measured; | ||
| 58 | boolean which; | ||
| 59 | |||
| 60 | /* Compute the total length of this pattern. */ | ||
| 61 | patternTotal = 0; | ||
| 62 | for (i = 0; i < gc.dashes.length; ++i) | ||
| 63 | patternTotal += gc.dashes[i]; | ||
| 64 | if ((gc.dashes.length & 1) != 0) | ||
| 65 | patternTotal += patternTotal; | ||
| 66 | |||
| 67 | /* Subtract as much of the offset as does not contribute to the | ||
| 68 | phase at the first pixel of the line. */ | ||
| 69 | offset = gc.dash_offset % patternTotal; | ||
| 70 | |||
| 71 | /* Set I to the first dash that ought to be drawn and WHICH to its | ||
| 72 | phase. */ | ||
| 73 | i = 0; | ||
| 74 | which = true; | ||
| 75 | while (offset >= gc.dashes[i]) | ||
| 76 | { | ||
| 77 | offset -= gc.dashes[i++]; | ||
| 78 | if (i >= gc.dashes.length) | ||
| 79 | i = 0; | ||
| 80 | which = !which; | ||
| 81 | } | ||
| 82 | |||
| 83 | /* Compute the length of the first visible segment. */ | ||
| 84 | dash_mag = gc.dashes[i] - offset; | ||
| 85 | |||
| 86 | /* Compute the slope of the line. */ | ||
| 87 | dx = x1 - x0; | ||
| 88 | dy = y1 - y0; | ||
| 89 | measured = measureLine (dx, dy); | ||
| 90 | dx = measured[0]; | ||
| 91 | dy = measured[1]; | ||
| 92 | rem = mag = measured[2]; | ||
| 93 | lx1 = x0; | ||
| 94 | ly1 = y0; | ||
| 95 | |||
| 96 | while (rem > 0f) | ||
| 97 | { | ||
| 98 | dash_mag = Math.min (dash_mag, rem); | ||
| 99 | rem -= dash_mag; | ||
| 100 | |||
| 101 | /* End of this segment. */ | ||
| 102 | x1 = (mag - rem) * dx + x0; | ||
| 103 | y1 = (mag - rem) * dy + y0; | ||
| 104 | |||
| 105 | if (which) | ||
| 106 | canvas.drawLine (lx1, ly1, x1, y1, paint); | ||
| 107 | which = !which; | ||
| 108 | |||
| 109 | /* Start of the next segment. */ | ||
| 110 | lx1 = x1; | ||
| 111 | ly1 = y1; | ||
| 112 | i++; | ||
| 113 | if (i >= gc.dashes.length) | ||
| 114 | i = 0; | ||
| 115 | dash_mag = gc.dashes[i]; | ||
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 28 | public static void | 119 | public static void |
| 29 | perform (EmacsDrawable drawable, EmacsGC gc, | 120 | perform (EmacsDrawable drawable, EmacsGC gc, |
| 30 | int x, int y, int x2, int y2) | 121 | int x, int y, int x2, int y2) |
| @@ -52,22 +143,20 @@ public final class EmacsDrawLine | |||
| 52 | if (canvas == null) | 143 | if (canvas == null) |
| 53 | return; | 144 | return; |
| 54 | 145 | ||
| 55 | paint.setStyle (Paint.Style.FILL); | ||
| 56 | |||
| 57 | /* Since drawLine has PostScript style behavior, adjust the | 146 | /* Since drawLine has PostScript style behavior, adjust the |
| 58 | coordinates appropriately. | 147 | coordinates appropriately. |
| 59 | 148 | ||
| 60 | The left most pixel of a straight line is always partially | 149 | The leftmost pixel of a straight line is always partially filled. |
| 61 | filled. Patch it in manually. */ | 150 | Patch it in manually. */ |
| 62 | 151 | ||
| 63 | if (gc.clip_mask == null) | 152 | if (gc.clip_mask == null) |
| 64 | { | 153 | { |
| 65 | canvas.drawLine ((float) x + 0.5f, (float) y + 0.5f, | 154 | if (gc.line_style != EmacsGC.GC_LINE_ON_OFF_DASH) |
| 66 | (float) x2 + 0.5f, (float) y2 + 0.5f, | 155 | canvas.drawLine ((float) x, (float) y, (float) x2, (float) y2, |
| 67 | paint); | 156 | paint); |
| 68 | 157 | else | |
| 69 | if (x2 > x) | 158 | polyDashPattern (gc, canvas, paint, (float) x, (float) y, |
| 70 | canvas.drawRect (new Rect (x, y, x + 1, y + 1), paint); | 159 | (float) x2, (float) y2); |
| 71 | } | 160 | } |
| 72 | 161 | ||
| 73 | /* DrawLine with clip mask not implemented; it is not used by | 162 | /* DrawLine with clip mask not implemented; it is not used by |
diff --git a/java/org/gnu/emacs/EmacsDrawRectangle.java b/java/org/gnu/emacs/EmacsDrawRectangle.java index a8f68c6530a..e40a7c16068 100644 --- a/java/org/gnu/emacs/EmacsDrawRectangle.java +++ b/java/org/gnu/emacs/EmacsDrawRectangle.java | |||
| @@ -52,6 +52,9 @@ public final class EmacsDrawRectangle | |||
| 52 | paint = gc.gcPaint; | 52 | paint = gc.gcPaint; |
| 53 | paint.setStyle (Paint.Style.STROKE); | 53 | paint.setStyle (Paint.Style.STROKE); |
| 54 | 54 | ||
| 55 | /* This graphics request, in contrast to X, does not presently | ||
| 56 | respect the GC's line style. */ | ||
| 57 | |||
| 55 | if (gc.clip_mask == null) | 58 | if (gc.clip_mask == null) |
| 56 | /* Use canvas.drawRect with a RectF. That seems to reliably | 59 | /* Use canvas.drawRect with a RectF. That seems to reliably |
| 57 | get PostScript behavior. */ | 60 | get PostScript behavior. */ |
diff --git a/java/org/gnu/emacs/EmacsGC.java b/java/org/gnu/emacs/EmacsGC.java index b2474c5bd76..ec2b9c9e475 100644 --- a/java/org/gnu/emacs/EmacsGC.java +++ b/java/org/gnu/emacs/EmacsGC.java | |||
| @@ -46,12 +46,17 @@ public final class EmacsGC extends EmacsHandleObject | |||
| 46 | public static final int GC_FILL_SOLID = 0; | 46 | public static final int GC_FILL_SOLID = 0; |
| 47 | public static final int GC_FILL_OPAQUE_STIPPLED = 1; | 47 | public static final int GC_FILL_OPAQUE_STIPPLED = 1; |
| 48 | 48 | ||
| 49 | public static final int GC_LINE_SOLID = 0; | ||
| 50 | public static final int GC_LINE_ON_OFF_DASH = 1; | ||
| 51 | |||
| 49 | public static final Xfermode xorAlu, srcInAlu; | 52 | public static final Xfermode xorAlu, srcInAlu; |
| 50 | 53 | ||
| 51 | public int function, fill_style; | 54 | public int function, fill_style; |
| 52 | public int foreground, background; | 55 | public int foreground, background; |
| 53 | public int clip_x_origin, clip_y_origin; | 56 | public int clip_x_origin, clip_y_origin; |
| 54 | public int ts_origin_x, ts_origin_y; | 57 | public int ts_origin_x, ts_origin_y; |
| 58 | public int line_style, line_width; | ||
| 59 | public int dashes[], dash_offset; | ||
| 55 | public Rect clip_rects[], real_clip_rects[]; | 60 | public Rect clip_rects[], real_clip_rects[]; |
| 56 | public EmacsPixmap clip_mask, stipple; | 61 | public EmacsPixmap clip_mask, stipple; |
| 57 | public Paint gcPaint; | 62 | public Paint gcPaint; |
| @@ -89,6 +94,10 @@ public final class EmacsGC extends EmacsHandleObject | |||
| 89 | foreground = 0; | 94 | foreground = 0; |
| 90 | background = 0xffffff; | 95 | background = 0xffffff; |
| 91 | gcPaint = new Paint (); | 96 | gcPaint = new Paint (); |
| 97 | |||
| 98 | /* Android S and above enable anti-aliasing unless explicitly told | ||
| 99 | otherwise. */ | ||
| 100 | gcPaint.setAntiAlias (false); | ||
| 92 | } | 101 | } |
| 93 | 102 | ||
| 94 | /* Mark this GC as dirty. Apply parameters to the paint and | 103 | /* Mark this GC as dirty. Apply parameters to the paint and |
| @@ -119,7 +128,8 @@ public final class EmacsGC extends EmacsHandleObject | |||
| 119 | clipRectID = ++clip_serial; | 128 | clipRectID = ++clip_serial; |
| 120 | } | 129 | } |
| 121 | 130 | ||
| 122 | gcPaint.setStrokeWidth (1f); | 131 | /* A line_width of 0 is equivalent to that of 1. */ |
| 132 | gcPaint.setStrokeWidth (line_width < 1 ? 1 : line_width); | ||
| 123 | gcPaint.setColor (foreground | 0xff000000); | 133 | gcPaint.setColor (foreground | 0xff000000); |
| 124 | gcPaint.setXfermode (function == GC_XOR | 134 | gcPaint.setXfermode (function == GC_XOR |
| 125 | ? xorAlu : srcInAlu); | 135 | ? xorAlu : srcInAlu); |