From a6c26592f1bbe194e6f4df159813d28b2f967803 Mon Sep 17 00:00:00 2001 From: Ed Schouten Date: Fri, 20 Dec 2013 21:31:50 +0000 Subject: [PATCH] Extend libteken to support CJK fullwidth characters. Introduce a new formatting bit (TF_CJK_RIGHT) that is set when putting a cell that is the right part of a CJK fullwidth character. This will allow drivers like vt(9) to support fullwidth characters properly. emaste@ has a patch to extend vt(9)'s font handling to increase the number of Unicode -> glyph maps from 2 ({normal,bold)} to 4 ({normal,bold} x {left,right}). This will need to use this formatting bit to determine whether to draw the left or right glyph. Reviewed by: emaste --- sys/dev/syscons/scterm-teken.c | 7 +++++++ sys/dev/vt/vt_font.c | 8 ++++++++ sys/kern/subr_terminal.c | 2 +- sys/sys/terminal.h | 5 ++--- sys/teken/demo/teken_demo.c | 7 ++++--- sys/teken/teken.h | 9 +++++---- sys/teken/teken_subr.h | 16 +++++++--------- 7 files changed, 34 insertions(+), 20 deletions(-) diff --git a/sys/dev/syscons/scterm-teken.c b/sys/dev/syscons/scterm-teken.c index e2e91189ee24..43f16faff982 100644 --- a/sys/dev/syscons/scterm-teken.c +++ b/sys/dev/syscons/scterm-teken.c @@ -553,7 +553,14 @@ scteken_putchar(void *arg, const teken_pos_t *tp, teken_char_t c, vm_offset_t p; int cursor, attr; + /* + * No support for printing right hand sides for CJK fullwidth + * characters. Simply print a space and assume that the left + * hand side describes the entire character. + */ attr = scteken_attr(a) << 8; + if (a->ta_format & TF_CJK_RIGHT) + c = ' '; #ifdef TEKEN_UTF8 scteken_get_cp437(&c, &attr); #endif /* TEKEN_UTF8 */ diff --git a/sys/dev/vt/vt_font.c b/sys/dev/vt/vt_font.c index eebe74066e69..50bcfe4e4994 100644 --- a/sys/dev/vt/vt_font.c +++ b/sys/dev/vt/vt_font.c @@ -87,7 +87,15 @@ vtfont_lookup(const struct vt_font *vf, term_char_t c) uint16_t dst; size_t stride; + /* + * No support for printing right hand sides for CJK fullwidth + * characters. Simply print a space and assume that the left + * hand side describes the entire character. + */ src = TCHAR_CHARACTER(c); + if (TCHAR_FORMAT(c) & TF_CJK_RIGHT) + src = ' '; + if (TCHAR_FORMAT(c) & TF_BOLD) { dst = vtfont_bisearch(vf->vf_bold, vf->vf_bold_length, src); if (dst != 0) diff --git a/sys/kern/subr_terminal.c b/sys/kern/subr_terminal.c index 91634f4483a2..54636e408c29 100644 --- a/sys/kern/subr_terminal.c +++ b/sys/kern/subr_terminal.c @@ -128,7 +128,7 @@ static const teken_attr_t default_message = { }; #define TCHAR_CREATE(c, a) ((c) | \ - (a)->ta_format << 22 | \ + (a)->ta_format << 21 | \ teken_256to8((a)->ta_fgcolor) << 26 | \ teken_256to8((a)->ta_bgcolor) << 29) diff --git a/sys/sys/terminal.h b/sys/sys/terminal.h index 146b9acdd084..e76190b500a5 100644 --- a/sys/sys/terminal.h +++ b/sys/sys/terminal.h @@ -62,15 +62,14 @@ struct tty; * * Bits Meaning * 0-20: Character value - * 21: Unused - * 22-25: Bold, underline, blink, reverse + * 21-25: Bold, underline, blink, reverse, right part of CJK fullwidth character * 26-28: Foreground color * 29-31: Background color */ typedef uint32_t term_char_t; #define TCHAR_CHARACTER(c) ((c) & 0x1fffff) -#define TCHAR_FORMAT(c) (((c) >> 22) & 0xf) +#define TCHAR_FORMAT(c) (((c) >> 21) & 0x1f) #define TCHAR_FGCOLOR(c) (((c) >> 26) & 0x7) #define TCHAR_BGCOLOR(c) ((c) >> 29) diff --git a/sys/teken/demo/teken_demo.c b/sys/teken/demo/teken_demo.c index 16bb4b7b198a..08323dc1a400 100644 --- a/sys/teken/demo/teken_demo.c +++ b/sys/teken/demo/teken_demo.c @@ -86,9 +86,10 @@ printchar(const teken_pos_t *p) assert(p->tp_row < NROWS); assert(p->tp_col < NCOLS); - getyx(stdscr, y, x); - px = &buffer[p->tp_col][p->tp_row]; + /* No need to print right hand side of CJK character manually. */ + if (px->a.ta_format & TF_CJK_RIGHT) + return; /* Convert Unicode to UTF-8. */ if (px->c < 0x80) { @@ -118,8 +119,8 @@ printchar(const teken_pos_t *p) bkgdset(attr | COLOR_PAIR(teken_256to8(px->a.ta_fgcolor) + 8 * teken_256to8(px->a.ta_bgcolor))); + getyx(stdscr, y, x); mvaddstr(p->tp_row, p->tp_col, str); - move(y, x); } diff --git a/sys/teken/teken.h b/sys/teken/teken.h index a9bca98e9669..27d1ce404740 100644 --- a/sys/teken/teken.h +++ b/sys/teken/teken.h @@ -41,10 +41,11 @@ typedef uint32_t teken_char_t; typedef unsigned short teken_unit_t; typedef unsigned char teken_format_t; -#define TF_BOLD 0x01 -#define TF_UNDERLINE 0x02 -#define TF_BLINK 0x04 -#define TF_REVERSE 0x08 +#define TF_BOLD 0x01 /* Bold character. */ +#define TF_UNDERLINE 0x02 /* Underline character. */ +#define TF_BLINK 0x04 /* Blinking character. */ +#define TF_REVERSE 0x08 /* Reverse rendered character. */ +#define TF_CJK_RIGHT 0x10 /* Right-hand side of CJK character. */ typedef unsigned char teken_color_t; #define TC_BLACK 0 #define TC_RED 1 diff --git a/sys/teken/teken_subr.h b/sys/teken/teken_subr.h index f25ab6aa34d0..be3ce8abfe83 100644 --- a/sys/teken/teken_subr.h +++ b/sys/teken/teken_subr.h @@ -791,21 +791,19 @@ teken_subr_do_putchar(teken_t *t, const teken_pos_t *tp, teken_char_t c, teken_funcs_copy(t, &ctr, &ctp); } + teken_funcs_putchar(t, tp, c, &t->t_curattr); + if (width == 2 && tp->tp_col + 1 < t->t_winsize.tp_col) { teken_pos_t tp2; + teken_attr_t attr; - /* - * Store a space behind double width characters before - * actually printing them. This prevents artifacts when - * the consumer doesn't render it using double width - * glyphs. - */ + /* Print second half of CJK fullwidth character. */ tp2.tp_row = tp->tp_row; tp2.tp_col = tp->tp_col + 1; - teken_funcs_putchar(t, &tp2, BLANK, &t->t_curattr); + attr = t->t_curattr; + attr.ta_format |= TF_CJK_RIGHT; + teken_funcs_putchar(t, &tp2, c, &attr); } - - teken_funcs_putchar(t, tp, c, &t->t_curattr); } static void