Wouldn't it be nice if we could do italic text on the console?

Well, now we can!

I've separated out this diff from my main 'console enhancement' patchset for
easier testing.

This is against -current as of a few minutes ago, and adds just the following
features:

* Italic text.
* Bold text using a real bold font instead of just brighter colour.

*******************
* Important note: *
*******************

Since neither the vt220 nor the pccon terminfo entries include the sitm and
ritm sequences, curses-based programs will not recognise the availability of
the italic attribute.

The xterm terminfo entry _does_ include the sitm and ritm sequences, and with
the changes that have gone into -current in the last few days, you should now
be able to set TERM=xterm at least for display testing purposes, (the main
issue being that F1-F4 won't work yet, because the necessary changes have not
been committed yet).

But in any case, even without TERM=xterm, you can test these new graphical
effects directly with the corresponding escape sequences.  I'll send a simple
test program in a separate email.

Index: dev/rasops/rasops.c
===================================================================
RCS file: /cvs/src/sys/dev/rasops/rasops.c,v
retrieving revision 1.69
diff -u -p -r1.69 rasops.c
--- dev/rasops/rasops.c 18 Jan 2023 11:08:49 -0000      1.69
+++ dev/rasops/rasops.c 18 Jan 2023 17:14:42 -0000
@@ -561,7 +561,7 @@ rasops_pack_cattr(void *cookie, int fg, 
        if ((flg & WSATTR_HILIT) != 0 && fg < 8)
                fg += 8;
 
-       *attr = (bg << 16) | (fg << 24) | (flg & WSATTR_UNDERLINE);
+       *attr = (bg << 16) | (fg << 24) | flg;
        return (0);
 }
 
@@ -585,7 +585,7 @@ rasops_pack_mattr(void *cookie, int fg, 
                bg = swap;
        }
 
-       *attr = (bg << 16) | (fg << 24) | (flg & WSATTR_UNDERLINE);
+       *attr = (bg << 16) | (fg << 24) | flg;
        return (0);
 }
 
Index: dev/rasops/rasops32.c
===================================================================
RCS file: /cvs/src/sys/dev/rasops/rasops32.c,v
retrieving revision 1.13
diff -u -p -r1.13 rasops32.c
--- dev/rasops/rasops32.c       18 Jan 2023 11:08:49 -0000      1.13
+++ dev/rasops/rasops32.c       18 Jan 2023 17:14:42 -0000
@@ -107,7 +107,26 @@ rasops32_putchar(void *cookie, int row, 
                }
        } else {
                uc -= ri->ri_font->firstchar;
-               fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
+
+               /* Choose font data based on bold and italic attributes */
+
+               u_char * font_dataset;
+
+               switch (attr & (WSATTR_HILIT | WSATTR_ITALIC)) {
+               case WSATTR_HILIT:
+                       font_dataset=(u_char *)ri->ri_font->data_bold;
+                       break;
+               case WSATTR_ITALIC:
+                       font_dataset=(u_char *)ri->ri_font->data_italic;
+                       break;
+               case (WSATTR_HILIT | WSATTR_ITALIC):
+                       font_dataset=(u_char *)ri->ri_font->data_bolditalic;
+                       break;
+               default:
+                       font_dataset=(u_char *)ri->ri_font->data;
+               }
+
+               fr = (font_dataset + uc * ri->ri_fontscale);
                fs = ri->ri_font->stride;
 
                /* double-pixel special cases for the common widths */
Index: dev/wscons/wsconsio.h
===================================================================
RCS file: /cvs/src/sys/dev/wscons/wsconsio.h,v
retrieving revision 1.98
diff -u -p -r1.98 wsconsio.h
--- dev/wscons/wsconsio.h       15 Jul 2022 17:57:27 -0000      1.98
+++ dev/wscons/wsconsio.h       18 Jan 2023 17:14:43 -0000
@@ -536,6 +536,9 @@ struct wsdisplay_font {
 #define        WSDISPLAY_FONTORDER_R2L         2
        void *cookie;
        void *data;
+       void *data_bold;
+       void *data_italic;
+       void *data_bolditalic;
 };
 #define WSDISPLAYIO_LDFONT     _IOW ('W', 77, struct wsdisplay_font)
 #define        WSDISPLAYIO_LSFONT      _IOWR('W', 78, struct wsdisplay_font)
Index: dev/wscons/wsdisplayvar.h
===================================================================
RCS file: /cvs/src/sys/dev/wscons/wsdisplayvar.h,v
retrieving revision 1.38
diff -u -p -r1.38 wsdisplayvar.h
--- dev/wscons/wsdisplayvar.h   13 Sep 2020 10:05:46 -0000      1.38
+++ dev/wscons/wsdisplayvar.h   18 Jan 2023 17:14:43 -0000
@@ -99,6 +99,7 @@ struct wsdisplay_emulops {
 #define WSATTR_BLINK   4
 #define WSATTR_UNDERLINE 8
 #define WSATTR_WSCOLORS 16
+#define WSATTR_ITALIC  32
 };
 
 #define        WSSCREEN_NAME_SIZE      16
Index: dev/wscons/wsemul_vt100_subr.c
===================================================================
RCS file: /cvs/src/sys/dev/wscons/wsemul_vt100_subr.c,v
retrieving revision 1.29
diff -u -p -r1.29 wsemul_vt100_subr.c
--- dev/wscons/wsemul_vt100_subr.c      12 Jan 2023 20:39:37 -0000      1.29
+++ dev/wscons/wsemul_vt100_subr.c      18 Jan 2023 17:14:43 -0000
@@ -588,6 +588,9 @@ wsemul_vt100_handle_csi(struct wsemul_vt
                        case 1: /* bold */
                                flags |= WSATTR_HILIT;
                                break;
+                       case 3: /* italic */
+                               flags |= WSATTR_ITALIC;
+                               break;
                        case 4: /* underline */
                                flags |= WSATTR_UNDERLINE;
                                break;
@@ -599,6 +602,9 @@ wsemul_vt100_handle_csi(struct wsemul_vt
                                break;
                        case 22: /* ~bold VT300 only */
                                flags &= ~WSATTR_HILIT;
+                               break;
+                       case 23: /* ~italic */
+                               flags &= ~WSATTR_ITALIC;
                                break;
                        case 24: /* ~underline VT300 only */
                                flags &= ~WSATTR_UNDERLINE;
Index: dev/wsfont/wsfont.c
===================================================================
RCS file: /cvs/src/sys/dev/wsfont/wsfont.c,v
retrieving revision 1.62
diff -u -p -r1.62 wsfont.c
--- dev/wsfont/wsfont.c 4 Apr 2022 19:53:15 -0000       1.62
+++ dev/wsfont/wsfont.c 18 Jan 2023 17:14:44 -0000
@@ -586,6 +586,63 @@ wsfont_lock(int cookie, struct wsdisplay
 
                lc = ++ent->lockcount;
                *ptr = ent->font;
+
+#define FONT_DATA ((*ptr)->data)
+#define FONT_DATA_BOLD ((*ptr)->data_bold)
+#define FONT_DATA_ITALIC ((*ptr)->data_italic)
+#define FONT_DATA_BOLDITALIC ((*ptr)->data_bolditalic)
+#define FONT_SLANT ((((*ptr)->fontheight))/2)
+#define FONT_BYTES_PER_GLYPH (((*ptr)->stride) * (((*ptr)->fontheight)))
+#define FONT_DATA_LEN FONT_BYTES_PER_GLYPH * ((*ptr)->numchars)
+#define FONT_STRIDE ((*ptr)->stride)
+
+               int i, j, row_data;
+
+               /*
+                * Create a bold version of the font:
+                *
+                * To produce the bold effect, we simply duplicate the set bits
+                * of the pixel data offset one pixel to the right, effectively
+                * 'overprinting' the glyph.  Better algorithms probably exist.
+                */
+               (*ptr)->data_bold=malloc(FONT_DATA_LEN, M_TEMP, M_WAITOK);
+               for (i=0; i < FONT_DATA_LEN ; i++) {
+                       *(unsigned char *)(FONT_DATA_BOLD + i) =
+                           *(unsigned char *)(FONT_DATA + i) |
+                           (*(unsigned char *)(FONT_DATA + i) >> 1) ;
+               }
+
+               /*
+                * Create an italic version of the font:
+                *
+                * Pixel data is increasingly offset to the left as we progress
+                * down the rows from the top of each glyph.  To minimise the
+                * overall visual shift to the left, we shift a fixed one bit to
+                * the right for each row.
+                */
+               (*ptr)->data_italic=malloc(FONT_DATA_LEN, M_TEMP, M_WAITOK);
+               for (i=0; i < FONT_DATA_LEN ; i += FONT_STRIDE) {
+                       row_data=0;
+                       for (j=0; j < FONT_STRIDE; j++) {
+                               row_data |=((*(unsigned char *)(FONT_DATA + i
+                                   + j) << (8 * (FONT_STRIDE-j-1))));
+                               }
+                       row_data=row_data << (i % FONT_BYTES_PER_GLYPH /
+                           FONT_SLANT) >> 1;
+                       for (j=0; j < FONT_STRIDE; j++) {
+                               *(unsigned char *)(FONT_DATA_ITALIC + i + j) =
+                                   (row_data >> (8 * (FONT_STRIDE-j-1)) & 
0xFF);
+                       }
+               }
+               /*
+                * Create a bold and italic version of the font:
+                */
+               (*ptr)->data_bolditalic=malloc(FONT_DATA_LEN, M_TEMP, M_WAITOK);
+               for (i=0; i < FONT_DATA_LEN ; i++) {
+                       *(unsigned char *)(FONT_DATA_BOLDITALIC + i) =
+                           *(unsigned char *)(FONT_DATA_ITALIC + i) |
+                           (*(unsigned char *)(FONT_DATA_ITALIC + i) >> 1) ;
+               }
        } else
                lc = -1;
 
@@ -600,6 +657,7 @@ int
 wsfont_unlock(int cookie)
 {
        struct font *ent;
+       struct wsdisplay_font *ptr;
        int s, lc;
 
        s = splhigh();
@@ -607,6 +665,10 @@ wsfont_unlock(int cookie)
        if ((ent = wsfont_find0(cookie)) != NULL) {
                if (ent->lockcount == 0)
                        panic("wsfont_unlock: font not locked");
+               ptr = ent->font;
+               free (ptr->data_bold, M_TEMP, 0);
+               free (ptr->data_italic, M_TEMP, 0);
+               free (ptr->data_bolditalic, M_TEMP, 0);
                lc = --ent->lockcount;
        } else
                lc = -1;

Reply via email to