1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

Support SGR 9 for strikethrough effect on text.

This is mostly easy: it's just like drawing an underline, except that
you put it at a different height in the character cell. The only
question is _where_ in the character cell.

Pango, and Windows GetOutlineTextMetrics, will tell you exactly where
the font wants to have it. Following xterm, I fall back to 3/8 of the
font's ascent (above the baseline) if either of those is unavailable.
This commit is contained in:
Simon Tatham 2020-08-13 21:08:53 +01:00
parent 334d87251e
commit 06a8d11964
6 changed files with 52 additions and 15 deletions

View File

@ -106,6 +106,7 @@
#define ATTR_BGMASK 0x003FE00U #define ATTR_BGMASK 0x003FE00U
#define ATTR_COLOURS 0x003FFFFU #define ATTR_COLOURS 0x003FFFFU
#define ATTR_DIM 0x1000000U #define ATTR_DIM 0x1000000U
#define ATTR_STRIKE 0x2000000U
#define ATTR_FGSHIFT 0 #define ATTR_FGSHIFT 0
#define ATTR_BGSHIFT 9 #define ATTR_BGSHIFT 9

View File

@ -4132,6 +4132,9 @@ static void term_out(Terminal *term)
case 7: /* enable reverse video */ case 7: /* enable reverse video */
term->curr_attr |= ATTR_REVERSE; term->curr_attr |= ATTR_REVERSE;
break; break;
case 9: /* enable strikethrough */
term->curr_attr |= ATTR_STRIKE;
break;
case 10: /* SCO acs off */ case 10: /* SCO acs off */
compatibility(SCOANSI); compatibility(SCOANSI);
if (term->no_remote_charset) break; if (term->no_remote_charset) break;
@ -4160,6 +4163,9 @@ static void term_out(Terminal *term)
compatibility2(OTHER, VT220); compatibility2(OTHER, VT220);
term->curr_attr &= ~ATTR_REVERSE; term->curr_attr &= ~ATTR_REVERSE;
break; break;
case 29: /* disable strikethrough */
term->curr_attr &= ~ATTR_STRIKE;
break;
case 30: case 30:
case 31: case 31:
case 32: case 32:

View File

@ -511,6 +511,7 @@ static unifont *x11font_create(GtkWidget *widget, const char *name,
xfont->u.height = xfont->u.ascent + xfont->u.descent; xfont->u.height = xfont->u.ascent + xfont->u.descent;
xfont->u.public_charset = pubcs; xfont->u.public_charset = pubcs;
xfont->u.want_fallback = true; xfont->u.want_fallback = true;
xfont->u.strikethrough_y = xfont->u.ascent - (xfont->u.ascent * 3 / 8);
#ifdef DRAW_TEXT_GDK #ifdef DRAW_TEXT_GDK
xfont->u.preferred_drawtype = DRAWTYPE_GDK; xfont->u.preferred_drawtype = DRAWTYPE_GDK;
#elif defined DRAW_TEXT_CAIRO #elif defined DRAW_TEXT_CAIRO
@ -1463,6 +1464,9 @@ static unifont *pangofont_create_internal(GtkWidget *widget,
pfont->u.descent = pfont->u.descent =
PANGO_PIXELS_CEIL(pango_font_metrics_get_descent(metrics)); PANGO_PIXELS_CEIL(pango_font_metrics_get_descent(metrics));
pfont->u.height = pfont->u.ascent + pfont->u.descent; pfont->u.height = pfont->u.ascent + pfont->u.descent;
pfont->u.strikethrough_y =
PANGO_PIXELS(pango_font_metrics_get_ascent(metrics) -
pango_font_metrics_get_strikethrough_position(metrics));
pfont->u.want_fallback = false; pfont->u.want_fallback = false;
#ifdef DRAW_TEXT_CAIRO #ifdef DRAW_TEXT_CAIRO
pfont->u.preferred_drawtype = DRAWTYPE_CAIRO; pfont->u.preferred_drawtype = DRAWTYPE_CAIRO;
@ -2242,6 +2246,7 @@ unifont *multifont_create(GtkWidget *widget, const char *name,
mfont->u.ascent = font->ascent; mfont->u.ascent = font->ascent;
mfont->u.descent = font->descent; mfont->u.descent = font->descent;
mfont->u.height = font->height; mfont->u.height = font->height;
mfont->u.strikethrough_y = font->strikethrough_y;
mfont->u.public_charset = font->public_charset; mfont->u.public_charset = font->public_charset;
mfont->u.want_fallback = false; /* shouldn't be needed, but just in case */ mfont->u.want_fallback = false; /* shouldn't be needed, but just in case */
mfont->u.preferred_drawtype = font->preferred_drawtype; mfont->u.preferred_drawtype = font->preferred_drawtype;

View File

@ -67,7 +67,7 @@ typedef struct unifont {
/* /*
* Font dimensions needed by clients. * Font dimensions needed by clients.
*/ */
int width, height, ascent, descent; int width, height, ascent, descent, strikethrough_y;
/* /*
* Indicates whether this font is capable of handling all glyphs * Indicates whether this font is capable of handling all glyphs

View File

@ -3887,6 +3887,14 @@ static void do_text_internal(
y*inst->font_height + uheight + inst->window_border); y*inst->font_height + uheight + inst->window_border);
} }
if (attr & ATTR_STRIKE) {
int sheight = inst->fonts[fontid]->strikethrough_y;
draw_line(inst, x*inst->font_width+inst->window_border,
y*inst->font_height + sheight + inst->window_border,
(x+len)*widefactor*inst->font_width-1+inst->window_border,
y*inst->font_height + sheight + inst->window_border);
}
if ((lattr & LATTR_MODE) != LATTR_NORM) { if ((lattr & LATTR_MODE) != LATTR_NORM) {
draw_stretch_after(inst, draw_stretch_after(inst,
x*inst->font_width+inst->window_border, x*inst->font_width+inst->window_border,

View File

@ -187,7 +187,7 @@ static bool bold_colours;
static enum { static enum {
UND_LINE, UND_FONT UND_LINE, UND_FONT
} und_mode; } und_mode;
static int descent; static int descent, font_strikethrough_y;
#define NCFGCOLOURS 22 #define NCFGCOLOURS 22
#define NEXTCOLOURS 240 #define NEXTCOLOURS 240
@ -1490,6 +1490,7 @@ static int get_font_width(HDC hdc, const TEXTMETRIC *tm)
static void init_fonts(int pick_width, int pick_height) static void init_fonts(int pick_width, int pick_height)
{ {
TEXTMETRIC tm; TEXTMETRIC tm;
OUTLINETEXTMETRIC otm;
CPINFO cpinfo; CPINFO cpinfo;
FontSpec *font; FontSpec *font;
int fontsize[3]; int fontsize[3];
@ -1539,6 +1540,10 @@ static void init_fonts(int pick_width, int pick_height)
SelectObject(hdc, fonts[FONT_NORMAL]); SelectObject(hdc, fonts[FONT_NORMAL]);
GetTextMetrics(hdc, &tm); GetTextMetrics(hdc, &tm);
if (GetOutlineTextMetrics(hdc, sizeof(otm), &otm))
font_strikethrough_y = tm.tmAscent - otm.otmsStrikeoutPosition;
else
font_strikethrough_y = tm.tmAscent - (tm.tmAscent * 3 / 8);
GetObject(fonts[FONT_NORMAL], sizeof(LOGFONT), &lfont); GetObject(fonts[FONT_NORMAL], sizeof(LOGFONT), &lfont);
@ -3462,6 +3467,25 @@ static void sys_cursor_update(void)
ImmReleaseContext(wgs.term_hwnd, hIMC); ImmReleaseContext(wgs.term_hwnd, hIMC);
} }
static void draw_horizontal_line_on_text(int y, int lattr, RECT line_box,
COLORREF colour)
{
if (lattr == LATTR_TOP || lattr == LATTR_BOT) {
y *= 2;
if (lattr == LATTR_BOT)
y -= font_height;
}
if (!(0 <= y && y < font_height))
return;
HPEN oldpen = SelectObject(wintw_hdc, CreatePen(PS_SOLID, 0, colour));
MoveToEx(wintw_hdc, line_box.left, line_box.top + y, NULL);
LineTo(wintw_hdc, line_box.right, line_box.top + y);
oldpen = SelectObject(wintw_hdc, oldpen);
DeleteObject(oldpen);
}
/* /*
* Draw a line of text in the window, at given character * Draw a line of text in the window, at given character
* coordinates, in given attributes. * coordinates, in given attributes.
@ -3838,20 +3862,13 @@ static void do_text_internal(
SetBkMode(wintw_hdc, TRANSPARENT); SetBkMode(wintw_hdc, TRANSPARENT);
opaque = false; opaque = false;
} }
if (lattr != LATTR_TOP && (force_manual_underline ||
(und_mode == UND_LINE
&& (attr & ATTR_UNDER)))) {
HPEN oldpen;
int dec = descent;
if (lattr == LATTR_BOT)
dec = dec * 2 - font_height;
oldpen = SelectObject(wintw_hdc, CreatePen(PS_SOLID, 0, fg)); if (lattr != LATTR_TOP && (force_manual_underline ||
MoveToEx(wintw_hdc, line_box.left, line_box.top + dec, NULL); (und_mode == UND_LINE && (attr & ATTR_UNDER))))
LineTo(wintw_hdc, line_box.right, line_box.top + dec); draw_horizontal_line_on_text(descent, lattr, line_box, fg);
oldpen = SelectObject(wintw_hdc, oldpen);
DeleteObject(oldpen); if (attr & ATTR_STRIKE)
} draw_horizontal_line_on_text(font_strikethrough_y, lattr, line_box, fg);
} }
/* /*