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.
This commit is contained in:
parent
b329358334
commit
e658a6938e
7 changed files with 382 additions and 31 deletions
|
|
@ -25,6 +25,97 @@ import android.graphics.Rect;
|
|||
|
||||
public final class EmacsDrawLine
|
||||
{
|
||||
/* Return the normalized slope and magnitude of a line whose extrema
|
||||
are DX and DY removed, on the X and Y axes respectively, from its
|
||||
origin point. */
|
||||
|
||||
private static float[]
|
||||
measureLine (float dx, float dy)
|
||||
{
|
||||
float hypot;
|
||||
|
||||
if (dx == 0f && dy == 0f)
|
||||
return new float[] { 0f, 0f, 0f, };
|
||||
|
||||
if (dx == 0f)
|
||||
return new float[] { 0f, dy > 0f ? 1f : -1f, Math.abs (dy), };
|
||||
else if (dy == 0f)
|
||||
return new float[] { dx > 0f ? 1f : -1f, 0f, Math.abs (dx), };
|
||||
else
|
||||
{
|
||||
hypot = (float) Math.hypot (dx, dy);
|
||||
return new float[] { dx / hypot, dy / hypot, hypot, };
|
||||
}
|
||||
}
|
||||
|
||||
private static void
|
||||
polyDashPattern (EmacsGC gc, Canvas canvas, Paint paint, float x0,
|
||||
float y0, float x1, float y1)
|
||||
{
|
||||
int patternTotal, i, offset;
|
||||
float dx, dy, mag, dash_mag, rem, lx1, ly1;
|
||||
float[] measured;
|
||||
boolean which;
|
||||
|
||||
/* Compute the total length of this pattern. */
|
||||
patternTotal = 0;
|
||||
for (i = 0; i < gc.dashes.length; ++i)
|
||||
patternTotal += gc.dashes[i];
|
||||
if ((gc.dashes.length & 1) != 0)
|
||||
patternTotal += patternTotal;
|
||||
|
||||
/* Subtract as much of the offset as does not contribute to the
|
||||
phase at the first pixel of the line. */
|
||||
offset = gc.dash_offset % patternTotal;
|
||||
|
||||
/* Set I to the first dash that ought to be drawn and WHICH to its
|
||||
phase. */
|
||||
i = 0;
|
||||
which = true;
|
||||
while (offset >= gc.dashes[i])
|
||||
{
|
||||
offset -= gc.dashes[i++];
|
||||
if (i >= gc.dashes.length)
|
||||
i = 0;
|
||||
which = !which;
|
||||
}
|
||||
|
||||
/* Compute the length of the first visible segment. */
|
||||
dash_mag = gc.dashes[i] - offset;
|
||||
|
||||
/* Compute the slope of the line. */
|
||||
dx = x1 - x0;
|
||||
dy = y1 - y0;
|
||||
measured = measureLine (dx, dy);
|
||||
dx = measured[0];
|
||||
dy = measured[1];
|
||||
rem = mag = measured[2];
|
||||
lx1 = x0;
|
||||
ly1 = y0;
|
||||
|
||||
while (rem > 0f)
|
||||
{
|
||||
dash_mag = Math.min (dash_mag, rem);
|
||||
rem -= dash_mag;
|
||||
|
||||
/* End of this segment. */
|
||||
x1 = (mag - rem) * dx + x0;
|
||||
y1 = (mag - rem) * dy + y0;
|
||||
|
||||
if (which)
|
||||
canvas.drawLine (lx1, ly1, x1, y1, paint);
|
||||
which = !which;
|
||||
|
||||
/* Start of the next segment. */
|
||||
lx1 = x1;
|
||||
ly1 = y1;
|
||||
i++;
|
||||
if (i >= gc.dashes.length)
|
||||
i = 0;
|
||||
dash_mag = gc.dashes[i];
|
||||
}
|
||||
}
|
||||
|
||||
public static void
|
||||
perform (EmacsDrawable drawable, EmacsGC gc,
|
||||
int x, int y, int x2, int y2)
|
||||
|
|
@ -52,22 +143,20 @@ public final class EmacsDrawLine
|
|||
if (canvas == null)
|
||||
return;
|
||||
|
||||
paint.setStyle (Paint.Style.FILL);
|
||||
|
||||
/* Since drawLine has PostScript style behavior, adjust the
|
||||
coordinates appropriately.
|
||||
|
||||
The left most pixel of a straight line is always partially
|
||||
filled. Patch it in manually. */
|
||||
The leftmost pixel of a straight line is always partially filled.
|
||||
Patch it in manually. */
|
||||
|
||||
if (gc.clip_mask == null)
|
||||
{
|
||||
canvas.drawLine ((float) x + 0.5f, (float) y + 0.5f,
|
||||
(float) x2 + 0.5f, (float) y2 + 0.5f,
|
||||
paint);
|
||||
|
||||
if (x2 > x)
|
||||
canvas.drawRect (new Rect (x, y, x + 1, y + 1), paint);
|
||||
if (gc.line_style != EmacsGC.GC_LINE_ON_OFF_DASH)
|
||||
canvas.drawLine ((float) x, (float) y, (float) x2, (float) y2,
|
||||
paint);
|
||||
else
|
||||
polyDashPattern (gc, canvas, paint, (float) x, (float) y,
|
||||
(float) x2, (float) y2);
|
||||
}
|
||||
|
||||
/* DrawLine with clip mask not implemented; it is not used by
|
||||
|
|
|
|||
|
|
@ -52,6 +52,9 @@ public final class EmacsDrawRectangle
|
|||
paint = gc.gcPaint;
|
||||
paint.setStyle (Paint.Style.STROKE);
|
||||
|
||||
/* This graphics request, in contrast to X, does not presently
|
||||
respect the GC's line style. */
|
||||
|
||||
if (gc.clip_mask == null)
|
||||
/* Use canvas.drawRect with a RectF. That seems to reliably
|
||||
get PostScript behavior. */
|
||||
|
|
|
|||
|
|
@ -46,12 +46,17 @@ public final class EmacsGC extends EmacsHandleObject
|
|||
public static final int GC_FILL_SOLID = 0;
|
||||
public static final int GC_FILL_OPAQUE_STIPPLED = 1;
|
||||
|
||||
public static final int GC_LINE_SOLID = 0;
|
||||
public static final int GC_LINE_ON_OFF_DASH = 1;
|
||||
|
||||
public static final Xfermode xorAlu, srcInAlu;
|
||||
|
||||
public int function, fill_style;
|
||||
public int foreground, background;
|
||||
public int clip_x_origin, clip_y_origin;
|
||||
public int ts_origin_x, ts_origin_y;
|
||||
public int line_style, line_width;
|
||||
public int dashes[], dash_offset;
|
||||
public Rect clip_rects[], real_clip_rects[];
|
||||
public EmacsPixmap clip_mask, stipple;
|
||||
public Paint gcPaint;
|
||||
|
|
@ -89,6 +94,10 @@ public final class EmacsGC extends EmacsHandleObject
|
|||
foreground = 0;
|
||||
background = 0xffffff;
|
||||
gcPaint = new Paint ();
|
||||
|
||||
/* Android S and above enable anti-aliasing unless explicitly told
|
||||
otherwise. */
|
||||
gcPaint.setAntiAlias (false);
|
||||
}
|
||||
|
||||
/* Mark this GC as dirty. Apply parameters to the paint and
|
||||
|
|
@ -119,7 +128,8 @@ public final class EmacsGC extends EmacsHandleObject
|
|||
clipRectID = ++clip_serial;
|
||||
}
|
||||
|
||||
gcPaint.setStrokeWidth (1f);
|
||||
/* A line_width of 0 is equivalent to that of 1. */
|
||||
gcPaint.setStrokeWidth (line_width < 1 ? 1 : line_width);
|
||||
gcPaint.setColor (foreground | 0xff000000);
|
||||
gcPaint.setXfermode (function == GC_XOR
|
||||
? xorAlu : srcInAlu);
|
||||
|
|
|
|||
153
src/android.c
153
src/android.c
|
|
@ -177,7 +177,9 @@ static jfieldID emacs_gc_function, emacs_gc_clip_rects;
|
|||
static jfieldID emacs_gc_clip_x_origin, emacs_gc_clip_y_origin;
|
||||
static jfieldID emacs_gc_stipple, emacs_gc_clip_mask;
|
||||
static jfieldID emacs_gc_fill_style, emacs_gc_ts_origin_x;
|
||||
static jfieldID emacs_gc_ts_origin_y;
|
||||
static jfieldID emacs_gc_ts_origin_y, emacs_gc_line_style;
|
||||
static jfieldID emacs_gc_line_width, emacs_gc_dash_offset;
|
||||
static jfieldID emacs_gc_dashes;
|
||||
|
||||
/* The constructor and one function. */
|
||||
static jmethodID emacs_gc_constructor, emacs_gc_mark_dirty;
|
||||
|
|
@ -3254,6 +3256,22 @@ android_init_emacs_gc_class (void)
|
|||
= (*android_java_env)->GetFieldID (android_java_env,
|
||||
emacs_gc_class,
|
||||
"ts_origin_y", "I");
|
||||
emacs_gc_line_style
|
||||
= (*android_java_env)->GetFieldID (android_java_env,
|
||||
emacs_gc_class,
|
||||
"line_style", "I");
|
||||
emacs_gc_line_width
|
||||
= (*android_java_env)->GetFieldID (android_java_env,
|
||||
emacs_gc_class,
|
||||
"line_width", "I");
|
||||
emacs_gc_dash_offset
|
||||
= (*android_java_env)->GetFieldID (android_java_env,
|
||||
emacs_gc_class,
|
||||
"dash_offset", "I");
|
||||
emacs_gc_dashes
|
||||
= (*android_java_env)->GetFieldID (android_java_env,
|
||||
emacs_gc_class,
|
||||
"dashes", "[I");
|
||||
}
|
||||
|
||||
struct android_gc *
|
||||
|
|
@ -3285,6 +3303,11 @@ android_create_gc (enum android_gc_value_mask mask,
|
|||
gc->stipple = ANDROID_NONE;
|
||||
gc->ts_x_origin = 0;
|
||||
gc->ts_y_origin = 0;
|
||||
gc->line_style = ANDROID_LINE_SOLID;
|
||||
gc->line_width = 0;
|
||||
gc->dash_offset = 0;
|
||||
gc->dashes = NULL;
|
||||
gc->n_segments = 0;
|
||||
|
||||
if (!gc->gcontext)
|
||||
{
|
||||
|
|
@ -3323,6 +3346,7 @@ android_free_gc (struct android_gc *gc)
|
|||
{
|
||||
android_destroy_handle (gc->gcontext);
|
||||
|
||||
xfree (gc->dashes);
|
||||
xfree (gc->clip_rects);
|
||||
xfree (gc);
|
||||
}
|
||||
|
|
@ -3332,7 +3356,7 @@ android_change_gc (struct android_gc *gc,
|
|||
enum android_gc_value_mask mask,
|
||||
struct android_gc_values *values)
|
||||
{
|
||||
jobject what, gcontext;
|
||||
jobject what, gcontext, array;
|
||||
jboolean clip_changed;
|
||||
|
||||
clip_changed = false;
|
||||
|
|
@ -3448,6 +3472,59 @@ android_change_gc (struct android_gc *gc,
|
|||
gc->ts_y_origin = values->ts_y_origin;
|
||||
}
|
||||
|
||||
if (mask & ANDROID_GC_LINE_STYLE)
|
||||
{
|
||||
(*android_java_env)->SetIntField (android_java_env,
|
||||
gcontext,
|
||||
emacs_gc_line_style,
|
||||
values->line_style);
|
||||
gc->line_style = values->line_style;
|
||||
}
|
||||
|
||||
if (mask & ANDROID_GC_LINE_WIDTH)
|
||||
{
|
||||
(*android_java_env)->SetIntField (android_java_env,
|
||||
gcontext,
|
||||
emacs_gc_line_width,
|
||||
values->line_width);
|
||||
gc->line_width = values->line_width;
|
||||
}
|
||||
|
||||
if (mask & ANDROID_GC_DASH_OFFSET)
|
||||
{
|
||||
(*android_java_env)->SetIntField (android_java_env,
|
||||
gcontext,
|
||||
emacs_gc_dash_offset,
|
||||
values->dash_offset);
|
||||
gc->dash_offset = values->dash_offset;
|
||||
}
|
||||
|
||||
if (mask & ANDROID_GC_DASH_LIST)
|
||||
{
|
||||
/* Compare the new dash pattern with the old. */
|
||||
if (gc->dashes && gc->n_segments == 1
|
||||
&& gc->dashes[0] == values->dash)
|
||||
/* If they be identical, nothing needs to change. */
|
||||
mask &= ~ANDROID_GC_DASH_LIST;
|
||||
else
|
||||
{
|
||||
if (gc->n_segments != 1)
|
||||
gc->dashes = xrealloc (gc->dashes, sizeof *gc->dashes);
|
||||
gc->n_segments = 1;
|
||||
gc->dashes[0] = values->dash;
|
||||
array = (*android_java_env)->NewIntArray (android_java_env, 1);
|
||||
android_exception_check ();
|
||||
(*android_java_env)->SetIntArrayRegion (android_java_env,
|
||||
array, 0, 1,
|
||||
(jint *) &values->dash);
|
||||
(*android_java_env)->SetObjectField (android_java_env,
|
||||
gcontext,
|
||||
emacs_gc_dashes,
|
||||
array);
|
||||
ANDROID_DELETE_LOCAL_REF (array);
|
||||
}
|
||||
}
|
||||
|
||||
if (mask)
|
||||
{
|
||||
(*android_java_env)->CallNonvirtualVoidMethod (android_java_env,
|
||||
|
|
@ -3539,6 +3616,75 @@ android_set_clip_rectangles (struct android_gc *gc, int clip_x_origin,
|
|||
n_clip_rects * sizeof *gc->clip_rects);
|
||||
}
|
||||
|
||||
void
|
||||
android_set_dashes (struct android_gc *gc, int dash_offset,
|
||||
int *dash_list, int n)
|
||||
{
|
||||
int i;
|
||||
jobject array, gcontext;
|
||||
|
||||
gcontext = android_resolve_handle (gc->gcontext,
|
||||
ANDROID_HANDLE_GCONTEXT);
|
||||
|
||||
if (n == gc->n_segments
|
||||
&& (!gc->dashes || !memcmp (gc->dashes, dash_list,
|
||||
sizeof *dash_list * n)))
|
||||
/* No change in the dash list. */
|
||||
goto set_offset;
|
||||
|
||||
if (!n)
|
||||
{
|
||||
/* Reset the dash list to its initial empty state. */
|
||||
xfree (gc->dashes);
|
||||
gc->dashes = NULL;
|
||||
array = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the size of the array has not changed, it can be reused. */
|
||||
|
||||
if (n != gc->n_segments)
|
||||
{
|
||||
gc->dashes = xrealloc (gc->dashes, sizeof *gc->dashes * n);
|
||||
array = (*android_java_env)->NewIntArray (android_java_env, n);
|
||||
android_exception_check ();
|
||||
}
|
||||
else
|
||||
array = (*android_java_env)->GetObjectField (android_java_env,
|
||||
gcontext,
|
||||
emacs_gc_dashes);
|
||||
|
||||
/* Copy the list of segments into both arrays. */
|
||||
for (i = 0; i < n; ++i)
|
||||
gc->dashes[i] = dash_list[i];
|
||||
verify (sizeof (int) == sizeof (jint));
|
||||
(*android_java_env)->SetIntArrayRegion (android_java_env,
|
||||
array, 0, n,
|
||||
(jint *) dash_list);
|
||||
}
|
||||
|
||||
/* Replace the dash array in the GContext object if required. */
|
||||
if (n != gc->n_segments)
|
||||
{
|
||||
(*android_java_env)->SetObjectField (android_java_env,
|
||||
gcontext,
|
||||
emacs_gc_dashes,
|
||||
array);
|
||||
ANDROID_DELETE_LOCAL_REF (array);
|
||||
}
|
||||
|
||||
gc->n_segments = n;
|
||||
|
||||
set_offset:
|
||||
/* And the offset. */
|
||||
if (dash_offset != gc->dash_offset)
|
||||
(*android_java_env)->SetIntField (android_java_env,
|
||||
gcontext,
|
||||
emacs_gc_dash_offset,
|
||||
dash_offset);
|
||||
gc->dash_offset = dash_offset;
|
||||
}
|
||||
|
||||
void
|
||||
android_reparent_window (android_window w, android_window parent_handle,
|
||||
int x, int y)
|
||||
|
|
@ -3690,7 +3836,8 @@ android_get_gc_values (struct android_gc *gc,
|
|||
values->ts_y_origin = gc->ts_y_origin;
|
||||
|
||||
/* Fields involving handles are not used by Emacs, and thus not
|
||||
implemented */
|
||||
implemented. In addition, the size of GCClipMask and GCDashList is
|
||||
not static, precluding their retrieval. */
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -71,6 +71,10 @@ enum android_gc_value_mask
|
|||
ANDROID_GC_FILL_STYLE = (1 << 7),
|
||||
ANDROID_GC_TILE_STIP_X_ORIGIN = (1 << 8),
|
||||
ANDROID_GC_TILE_STIP_Y_ORIGIN = (1 << 9),
|
||||
ANDROID_GC_LINE_STYLE = (1 << 10),
|
||||
ANDROID_GC_LINE_WIDTH = (1 << 11),
|
||||
ANDROID_GC_DASH_LIST = (1 << 12),
|
||||
ANDROID_GC_DASH_OFFSET = (1 << 13),
|
||||
};
|
||||
|
||||
enum android_fill_style
|
||||
|
|
@ -79,6 +83,12 @@ enum android_fill_style
|
|||
ANDROID_FILL_OPAQUE_STIPPLED = 1,
|
||||
};
|
||||
|
||||
enum android_line_style
|
||||
{
|
||||
ANDROID_LINE_SOLID = 0,
|
||||
ANDROID_LINE_ON_OFF_DASH = 1,
|
||||
};
|
||||
|
||||
enum android_window_value_mask
|
||||
{
|
||||
ANDROID_CW_BACK_PIXEL = (1 << 1),
|
||||
|
|
@ -114,6 +124,18 @@ struct android_gc_values
|
|||
|
||||
/* The tile-stipple X and Y origins. */
|
||||
int ts_x_origin, ts_y_origin;
|
||||
|
||||
/* The line style. */
|
||||
enum android_line_style line_style;
|
||||
|
||||
/* The line width. */
|
||||
int line_width;
|
||||
|
||||
/* Offset in pixels into the dash pattern specified below. */
|
||||
int dash_offset;
|
||||
|
||||
/* One integer providing both segments of a even-odd dash pattern. */
|
||||
int dash;
|
||||
};
|
||||
|
||||
/* X-like graphics context structure. This is implemented in
|
||||
|
|
@ -152,6 +174,18 @@ struct android_gc
|
|||
|
||||
/* The tile-stipple X and Y origins. */
|
||||
int ts_x_origin, ts_y_origin;
|
||||
|
||||
/* The line style. */
|
||||
enum android_line_style line_style;
|
||||
|
||||
/* The line width. */
|
||||
int line_width;
|
||||
|
||||
/* Offset in pixels into the dash pattern specified below. */
|
||||
int dash_offset;
|
||||
|
||||
/* The segments of an even/odd dash pattern. */
|
||||
int *dashes, n_segments;
|
||||
};
|
||||
|
||||
enum android_swap_action
|
||||
|
|
@ -675,6 +709,7 @@ extern void android_set_clip_rectangles (struct android_gc *,
|
|||
int, int,
|
||||
struct android_rectangle *,
|
||||
int);
|
||||
extern void android_set_dashes (struct android_gc *, int, int *, int);
|
||||
extern void android_change_gc (struct android_gc *,
|
||||
enum android_gc_value_mask,
|
||||
struct android_gc_values *);
|
||||
|
|
|
|||
|
|
@ -4031,6 +4031,80 @@ android_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
|
|||
s->char2b = NULL;
|
||||
}
|
||||
|
||||
/* Draw a dashed underline of thickness THICKNESS and width WIDTH onto F
|
||||
at a vertical offset of OFFSET from the position of the glyph string
|
||||
S, with each segment SEGMENT pixels in length. */
|
||||
|
||||
static void
|
||||
android_draw_dash (struct frame *f, struct glyph_string *s, int width,
|
||||
int segment, int offset, int thickness)
|
||||
{
|
||||
struct android_gc *gc;
|
||||
struct android_gc_values gcv;
|
||||
int y_center;
|
||||
|
||||
/* Configure the GC, the dash pattern and a suitable offset. */
|
||||
gc = s->gc;
|
||||
|
||||
gcv.line_style = ANDROID_LINE_ON_OFF_DASH;
|
||||
gcv.line_width = thickness;
|
||||
android_change_gc (s->gc, (ANDROID_GC_LINE_STYLE
|
||||
| ANDROID_GC_LINE_WIDTH), &gcv);
|
||||
android_set_dashes (s->gc, s->x, &segment, 1);
|
||||
|
||||
/* Offset the origin of the line by half the line width. */
|
||||
y_center = s->ybase + offset + thickness / 2;
|
||||
android_draw_line (FRAME_ANDROID_WINDOW (f), gc,
|
||||
s->x, y_center, s->x + width, y_center);
|
||||
|
||||
/* Restore the initial line style. */
|
||||
gcv.line_style = ANDROID_LINE_SOLID;
|
||||
gcv.line_width = 1;
|
||||
android_change_gc (s->gc, (ANDROID_GC_LINE_STYLE
|
||||
| ANDROID_GC_LINE_WIDTH), &gcv);
|
||||
}
|
||||
|
||||
/* Draw an underline of STYLE onto F at an offset of POSITION from the
|
||||
baseline of the glyph string S, DECORATION_WIDTH in length, and
|
||||
THICKNESS in height. */
|
||||
|
||||
static void
|
||||
android_fill_underline (struct frame *f, struct glyph_string *s,
|
||||
enum face_underline_type style, int position,
|
||||
int decoration_width, int thickness)
|
||||
{
|
||||
int segment;
|
||||
|
||||
segment = thickness * 3;
|
||||
|
||||
switch (style)
|
||||
{
|
||||
/* FACE_UNDERLINE_DOUBLE_LINE is treated identically to SINGLE, as
|
||||
the second line will be filled by another invocation of this
|
||||
function. */
|
||||
case FACE_UNDERLINE_SINGLE:
|
||||
case FACE_UNDERLINE_DOUBLE_LINE:
|
||||
android_fill_rectangle (FRAME_ANDROID_DRAWABLE (f),
|
||||
s->gc, s->x, s->ybase + position,
|
||||
decoration_width, thickness);
|
||||
break;
|
||||
|
||||
case FACE_UNDERLINE_DOTS:
|
||||
segment = thickness;
|
||||
FALLTHROUGH;
|
||||
|
||||
case FACE_UNDERLINE_DASHES:
|
||||
android_draw_dash (f, s, decoration_width, segment, position,
|
||||
thickness);
|
||||
break;
|
||||
|
||||
case FACE_NO_UNDERLINE:
|
||||
case FACE_UNDERLINE_WAVE:
|
||||
default:
|
||||
emacs_abort ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
android_draw_glyph_string (struct glyph_string *s)
|
||||
{
|
||||
|
|
@ -4167,16 +4241,13 @@ android_draw_glyph_string (struct glyph_string *s)
|
|||
android_set_foreground (s->gc, xgcv.foreground);
|
||||
}
|
||||
}
|
||||
else if (s->face->underline == FACE_UNDERLINE_SINGLE
|
||||
|| s->face->underline == FACE_UNDERLINE_DOUBLE_LINE)
|
||||
else if (s->face->underline >= FACE_UNDERLINE_SINGLE)
|
||||
{
|
||||
unsigned long thickness, position;
|
||||
int y;
|
||||
|
||||
if (s->prev
|
||||
&& ((s->prev->face->underline == FACE_UNDERLINE_SINGLE)
|
||||
|| (s->prev->face->underline
|
||||
== FACE_UNDERLINE_DOUBLE_LINE))
|
||||
&& (s->prev->face->underline != FACE_UNDERLINE_WAVE
|
||||
&& s->prev->face->underline >= FACE_UNDERLINE_SINGLE)
|
||||
&& (s->prev->face->underline_at_descent_line_p
|
||||
== s->face->underline_at_descent_line_p)
|
||||
&& (s->prev->face->underline_pixels_above_descent_line
|
||||
|
|
@ -4257,18 +4328,16 @@ android_draw_glyph_string (struct glyph_string *s)
|
|||
{
|
||||
struct android_gc_values xgcv;
|
||||
|
||||
y = s->ybase + position;
|
||||
if (s->face->underline_defaulted_p)
|
||||
android_fill_rectangle (FRAME_ANDROID_DRAWABLE (s->f), s->gc,
|
||||
s->x, y, decoration_width, thickness);
|
||||
else
|
||||
if (!s->face->underline_defaulted_p)
|
||||
{
|
||||
android_get_gc_values (s->gc, ANDROID_GC_FOREGROUND, &xgcv);
|
||||
android_set_foreground (s->gc, s->face->underline_color);
|
||||
android_fill_rectangle (FRAME_ANDROID_DRAWABLE (s->f), s->gc,
|
||||
s->x, y, decoration_width, thickness);
|
||||
}
|
||||
|
||||
android_fill_underline (s->f, s, s->face->underline,
|
||||
position, decoration_width,
|
||||
thickness);
|
||||
|
||||
/* Place a second underline above the first if this was
|
||||
requested in the face specification. */
|
||||
|
||||
|
|
@ -4276,9 +4345,8 @@ android_draw_glyph_string (struct glyph_string *s)
|
|||
{
|
||||
/* Compute the position of the second underline. */
|
||||
position = position - thickness - 1;
|
||||
y = s->ybase + position;
|
||||
android_fill_rectangle (FRAME_ANDROID_DRAWABLE (s->f),
|
||||
s->gc, s->x, y, decoration_width,
|
||||
android_fill_underline (s->f, s, s->face->underline,
|
||||
position, decoration_width,
|
||||
thickness);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10851,7 +10851,6 @@ x_draw_dash (struct frame *f, struct glyph_string *s, int width,
|
|||
gc = s->gc;
|
||||
display = FRAME_X_DISPLAY (f);
|
||||
|
||||
XGetGCValues (display, s->gc, GCLineStyle, &gcv);
|
||||
gcv.line_style = LineOnOffDash;
|
||||
gcv.line_width = thickness;
|
||||
XChangeGC (display, s->gc, GCLineStyle | GCLineWidth, &gcv);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue