Implement dots and dashes on MS-Windows

* src/haikuterm.c (haiku_draw_dash): Correct whitespace error.

* src/w32term.c (w32_draw_dash, w32_fill_underline)
(w32_draw_glyph_string): Port display of dash and dot underline
styles from X.
scratch/igc
Po Lu 2024-05-10 16:44:35 +08:00
parent 4306aba2d0
commit 0f67ddd8d9
2 changed files with 91 additions and 13 deletions

View File

@ -839,7 +839,7 @@ haiku_draw_dash (struct frame *f, struct glyph_string *s, int width,
s->x + width - 1),
y_center);
which = !which;
which = !which;
}
}

View File

@ -2535,6 +2535,89 @@ w32_draw_stretch_glyph_string (struct glyph_string *s)
s->background_filled_p = true;
}
/* 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, and in the color
FOREGROUND. */
static void
w32_draw_dash (struct frame *f, struct glyph_string *s,
COLORREF foreground, int width, char segment,
int offset, int thickness)
{
int y_base, which, length, x, doffset;
HDC hdc = s->hdc;
/* A pen with PS_DASH (or PS_DOT) is unsuitable for two reasons: first
that PS_DASH does not accept width values greater than 1, with
itself considered equivalent to PS_SOLID if such a value be
specified, and second that it does not provide for an offset to be
applied to the pattern, absent which Emacs cannot align dashes that
are displayed at locations not multiples of each other. I can't be
bothered to research this matter further, so, for want of a better
option, draw the specified pattern manually. */
y_base = s->ybase + offset;
/* Remove redundant portions of OFFSET. */
doffset = s->x % (segment * 2);
/* Set which to the phase of the first dash that ought to be drawn and
length to its length. */
which = doffset < segment;
length = segment - (s->x % segment);
/* Begin drawing this dash. */
for (x = s->x; x < s->x + width; x += length, length = segment)
{
if (which)
w32_fill_area (f, hdc, foreground, x, y_base, length,
thickness);
which = !which;
}
}
/* Draw an underline of STYLE onto F at an offset of POSITION from the
baseline of the glyph string S, in the color FOREGROUND that is
THICKNESS in height. */
static void
w32_fill_underline (struct frame *f, struct glyph_string *s,
COLORREF foreground,
enum face_underline_type style, int position,
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:
w32_fill_area (s->f, s->hdc, foreground, s->x,
s->ybase + position, s->width, thickness);
break;
case FACE_UNDERLINE_DOTS:
segment = thickness;
FALLTHROUGH;
case FACE_UNDERLINE_DASHES:
w32_draw_dash (f, s, foreground, s->width, segment, position,
thickness);
break;
case FACE_NO_UNDERLINE:
case FACE_UNDERLINE_WAVE:
default:
emacs_abort ();
}
}
/* Draw glyph string S. */
@ -2652,17 +2735,14 @@ w32_draw_glyph_string (struct glyph_string *s)
w32_draw_underwave (s, color);
}
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;
COLORREF foreground;
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
@ -2739,15 +2819,14 @@ w32_draw_glyph_string (struct glyph_string *s)
thickness = (s->y + s->height) - (s->ybase + position);
s->underline_thickness = thickness;
s->underline_position = position;
y = s->ybase + position;
if (s->face->underline_defaulted_p)
foreground = s->gc->foreground;
else
foreground = s->face->underline_color;
w32_fill_area (s->f, s->hdc, foreground, s->x, y,
s->width, thickness);
w32_fill_underline (s->f, s, foreground, s->face->underline,
position, thickness);
/* Place a second underline above the first if this was
requested in the face specification. */
@ -2756,9 +2835,8 @@ w32_draw_glyph_string (struct glyph_string *s)
{
/* Compute the position of the second underline. */
position = position - thickness - 1;
y = s->ybase + position;
w32_fill_area (s->f, s->hdc, foreground, s->x, y,
s->width, thickness);
w32_fill_underline (s->f, s, foreground, s->face->underline,
position, thickness);
}
}
}