[FZH] [D] CJK console font support

microcai microcai在fedoraproject.org
星期五 十一月 26 04:01:49 UTC 2010


在 2010年11月26日 上午11:28,microcai <microcai在fedoraproject.org> 写道:
> 进度报告:
>
> 1) 豹哥's code  clean up. 大部分代码被替换成我写的了。使用了  vt.c 自带的
> id_double_width 来判断是否是全角字符。而不是死死的(豹哥的做法)认定
> 非 ASCII 字符都是 CJK 字符。
>
> 2) 添加了大量注释。方便 code review.
>
> ====
> TODO:
> 改写并最终支持 setfont 使用 .pcf 字体。这样就可以直接使用文泉驿字体了。
>

额,忘记附加补丁了

下面是补丁 2  个

这个是为内核添加 UNICODE 字体支持的补丁。
UNICODE字体很大,我就不附到邮件上了
大家可以到 http://minilab.tk/0002-add-cjk-font-that-has-65536-chars.patch
下载 CJK 字体补丁。

From 122ae5301b43f205474a1076f84edb09ee7ed5af Mon Sep 17 00:00:00 2001
From: microcai <microcai在fedoraproject.org>
Date: Fri, 26 Nov 2010 10:39:22 +0800
Subject: [PATCH 1/2] support UNICODE font has more that 255 chars

---
 drivers/char/selection.c               |    5 +-
 drivers/char/vt.c                      |  214 +++++++++++++++++++++++++------
 drivers/video/console/bitblit.c        |   57 +++++++--
 drivers/video/console/fbcon.c          |   70 ++++++++---
 drivers/video/console/fbcon.h          |    3 +
 drivers/video/console/fbcon_ccw.c      |   33 +++++-
 drivers/video/console/fbcon_cw.c       |   29 ++++-
 drivers/video/console/fbcon_ud.c       |   42 ++++++-
 drivers/video/console/font_10x18.c     |    1 +
 drivers/video/console/font_6x11.c      |    1 +
 drivers/video/console/font_7x14.c      |    1 +
 drivers/video/console/font_8x16.c      |    1 +
 drivers/video/console/font_8x8.c       |    1 +
 drivers/video/console/font_acorn_8x8.c |    1 +
 drivers/video/console/font_mini_4x6.c  |    1 +
 drivers/video/console/font_pearl_8x8.c |    1 +
 drivers/video/console/font_sun12x22.c  |    1 +
 drivers/video/console/font_sun8x16.c   |    1 +
 include/linux/font.h                   |    1 +
 19 files changed, 381 insertions(+), 83 deletions(-)

diff --git a/drivers/char/selection.c b/drivers/char/selection.c
index ebae344..0654717 100644
--- a/drivers/char/selection.c
+++ b/drivers/char/selection.c
@@ -60,8 +60,7 @@ static inline void highlight_pointer(const int where)
 static u16
 sel_pos(int n)
 {
-	return inverse_translate(sel_cons, screen_glyph(sel_cons, n),
-				use_unicode);
+	return screen_glyph(sel_cons, n);
 }

 /* remove the current selection highlight, if any,
@@ -296,6 +295,8 @@ int set_selection(const struct tiocl_selection
__user *sel, struct tty_struct *t
 			}
 			obp = bp;
 		}
+		if (c > 0x80)
+			i += 2;
 	}
 	sel_buffer_lth = bp - sel_buffer;
 	return 0;
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index bf07b26..3b7052f 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -288,6 +288,20 @@ static inline unsigned short *screenpos(struct
vc_data *vc, int offset, int view
 	return p;
 }

+static inline unsigned short *screenpos_utf8(struct vc_data *vc, int
offset, int viewed)
+{
+	unsigned short *p;
+
+	if (!viewed)
+		p = (unsigned short *)(vc->vc_origin + offset + vc->vc_screenbuf_size);
+	else if (!vc->vc_sw->con_screen_pos)
+		p = (unsigned short *)(vc->vc_visible_origin + offset +
vc->vc_screenbuf_size);
+	else
+		p = vc->vc_sw->con_screen_pos(vc, -offset - 1);
+	return p;
+}
+
+
 /* Called  from the keyboard irq path.. */
 static inline void scrolldelta(int lines)
 {
@@ -318,6 +332,11 @@ static void scrup(struct vc_data *vc, unsigned
int t, unsigned int b, int nr)
 	scr_memmovew(d, s, (b - t - nr) * vc->vc_size_row);
 	scr_memsetw(d + (b - t - nr) * vc->vc_cols, vc->vc_video_erase_char,
 		    vc->vc_size_row * nr);
+	d += (vc->vc_screenbuf_size >> 1);
+	s += (vc->vc_screenbuf_size >> 1);
+	scr_memmovew(d, s, (b - t - nr) * vc->vc_size_row);
+	scr_memsetw(d + (b - t - nr) * vc->vc_cols, 0,
+		    vc->vc_size_row * nr);
 }

 static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
@@ -335,6 +354,9 @@ static void scrdown(struct vc_data *vc, unsigned
int t, unsigned int b, int nr)
 	step = vc->vc_cols * nr;
 	scr_memmovew(s + step, s, (b - t - nr) * vc->vc_size_row);
 	scr_memsetw(s, vc->vc_video_erase_char, 2 * step);
+  	s += (vc->vc_screenbuf_size >> 1);
+  	scr_memmovew(s + step, s, (b - t - nr) * vc->vc_size_row);
+  	scr_memsetw(s, 0, 2 * step);
 }

 static void do_update_region(struct vc_data *vc, unsigned long start,
int count)
@@ -502,6 +524,8 @@ void complement_pos(struct vc_data *vc, int offset)
 	static int old_offset = -1;
 	static unsigned short old;
 	static unsigned short oldx, oldy;
+	static unsigned short *p_ext = NULL;
+	static unsigned short old_ext = 0;

 	WARN_CONSOLE_UNLOCKED();

@@ -509,7 +533,7 @@ void complement_pos(struct vc_data *vc, int offset)
 	    old_offset < vc->vc_screenbuf_size) {
 		scr_writew(old, screenpos(vc, old_offset, 1));
 		if (DO_UPDATE(vc))
-			vc->vc_sw->con_putc(vc, old, oldy, oldx);
+			vc->vc_sw->con_putc(vc, (old_ext << 16)|old, oldy, oldx);
 	}

 	old_offset = offset;
@@ -519,13 +543,15 @@ void complement_pos(struct vc_data *vc, int offset)
 		unsigned short new;
 		unsigned short *p;
 		p = screenpos(vc, offset, 1);
+		p_ext = screenpos_utf8(vc, offset, 1);
 		old = scr_readw(p);
+		old_ext = scr_readw(p_ext);
 		new = old ^ vc->vc_complement_mask;
 		scr_writew(new, p);
 		if (DO_UPDATE(vc)) {
 			oldx = (offset >> 1) % vc->vc_cols;
 			oldy = (offset >> 1) / vc->vc_cols;
-			vc->vc_sw->con_putc(vc, new, oldy, oldx);
+			vc->vc_sw->con_putc(vc, (old_ext << 16)|new, oldy, oldx);
 		}
 	}

@@ -789,7 +815,7 @@ int vc_allocate(unsigned int currcons)	/* return 0
on success */
 	    visual_init(vc, currcons, 1);
 	    if (!*vc->vc_uni_pagedir_loc)
 		con_set_default_unimap(vc);
-	    vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
+	    vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size * 2, GFP_KERNEL);
 	    if (!vc->vc_screenbuf) {
 		kfree(vc);
 		vc_cons[currcons].d = NULL;
@@ -873,7 +899,7 @@ static int vc_do_resize(struct tty_struct *tty,
struct vc_data *vc,
 	if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
 		return 0;

-	newscreen = kmalloc(new_screen_size, GFP_USER);
+	newscreen = kmalloc(new_screen_size * 2, GFP_USER);
 	if (!newscreen)
 		return -ENOMEM;

@@ -922,15 +948,23 @@ static int vc_do_resize(struct tty_struct *tty,
struct vc_data *vc,
 	while (old_origin < end) {
 		scr_memcpyw((unsigned short *) new_origin,
 			    (unsigned short *) old_origin, rlth);
-		if (rrem)
+ 		scr_memcpyw((unsigned short *) new_origin + (new_screen_size >> 1),
+ 			    (unsigned short *) old_origin + (old_screen_size >> 1), rlth);
+		if (rrem){
 			scr_memsetw((void *)(new_origin + rlth),
 				    vc->vc_video_erase_char, rrem);
+ 			scr_memsetw((void *)(new_origin + rlth + (new_screen_size)),
+ 				    vc->vc_video_erase_char, rrem);
+		}
 		old_origin += old_row_size;
 		new_origin += new_row_size;
 	}
-	if (new_scr_end > new_origin)
+	if (new_scr_end > new_origin){
 		scr_memsetw((void *)new_origin, vc->vc_video_erase_char,
 			    new_scr_end - new_origin);
+ 		scr_memsetw((void *)new_origin + (new_screen_size), vc->vc_video_erase_char,
+ 			    new_scr_end - new_origin);
+	}
 	kfree(vc->vc_screenbuf);
 	vc->vc_screenbuf = newscreen;
 	vc->vc_screenbuf_size = new_screen_size;
@@ -2121,7 +2155,7 @@ static int do_con_write(struct tty_struct *tty,
const unsigned char *buf, int co
 	}
 #endif

-	int c, tc, ok, n = 0, draw_x = -1;
+	int c, tc, tc_1 , ok, n = 0, draw_x = -1;
 	unsigned int currcons;
 	unsigned long draw_from = 0, draw_to = 0;
 	struct vc_data *vc;
@@ -2131,6 +2165,7 @@ static int do_con_write(struct tty_struct *tty,
const unsigned char *buf, int co
 	uint8_t inverse;
 	uint8_t width;
 	u16 himask, charmask;
+ 	int is_utf8 = 0;

 	if (in_interrupt())
 		return count;
@@ -2171,6 +2206,8 @@ static int do_con_write(struct tty_struct *tty,
const unsigned char *buf, int co
 		rescan = 0;
 		inverse = 0;
 		width = 1;
+		vc->vc_utf = 1;
+		vc->vc_disp_ctrl = 0;

 		/* Do no translation at all in control states */
 		if (vc->vc_state != ESnormal) {
@@ -2212,6 +2249,7 @@ rescan_last_byte:
 			    vc->vc_utf_count = 0;
 			    c = 0xfffd;
 			} else if (c > 0x7f) {
+			    is_utf8 = 1;
 			    /* First byte of a multibyte sequence received */
 			    vc->vc_npar = 0;
 			    if ((c & 0xe0) == 0xc0) {
@@ -2237,8 +2275,9 @@ rescan_last_byte:
 				/* Still need some bytes */
 				continue;
 			    }
+			} else {
+				is_utf8 = 0;
 			}
-			/* Nothing to do if an ASCII byte was received */
 		    }
 		    /* End of UTF-8 decoding. */
 		    /* c is the received character, or U+FFFD for invalid sequences. */
@@ -2316,39 +2355,124 @@ rescan_last_byte:
 			}

 			while (1) {
-				if (vc->vc_need_wrap || vc->vc_decim)
-					FLUSH
-				if (vc->vc_need_wrap) {
-					cr(vc);
-					lf(vc);
-				}
-				if (vc->vc_decim)
-					insert_char(vc, 1);
-				scr_writew(himask ?
-					     ((vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) +
(tc & 0xff) :
-					     (vc_attr << 8) + tc,
-					   (u16 *) vc->vc_pos);
-				if (DO_UPDATE(vc) && draw_x < 0) {
-					draw_x = vc->vc_x;
-					draw_from = vc->vc_pos;
-				}
-				if (vc->vc_x == vc->vc_cols - 1) {
-					vc->vc_need_wrap = vc->vc_decawm;
-					draw_to = vc->vc_pos + 2;
-				} else {
-					vc->vc_x++;
-					draw_to = (vc->vc_pos += 2);
-				}
+				if(is_utf8 == 0) {
+					if (vc->vc_need_wrap || vc->vc_decim)
+						FLUSH
+					if (vc->vc_need_wrap) {
+						cr(vc);
+						lf(vc);
+					}
+					if (vc->vc_decim)
+						insert_char(vc, 1);
+					scr_writew(himask ?
+						     ((vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) +
(tc & 0xff) :
+						     (vc_attr << 8) + tc,
+						   (u16 *) vc->vc_pos);
+					scr_writew(0, (u16 *) vc->vc_pos + (vc->vc_screenbuf_size >> 1));
+					if (DO_UPDATE(vc) && draw_x < 0) {
+						draw_x = vc->vc_x;
+						draw_from = vc->vc_pos;
+					}
+					if (vc->vc_x == vc->vc_cols - 1) {
+						vc->vc_need_wrap = vc->vc_decawm;
+						draw_to = vc->vc_pos + 2;
+					} else {
+						vc->vc_x++;
+						draw_to = (vc->vc_pos += 2);
+					}
+
+					if (!--width) break;
+
+					tc = conv_uni_to_pc(vc, ' '); /* A space is printed in the
second column */
+					if (tc < 0) tc = ' ';
+
+					notify_write(vc, c);
+
+					if (inverse) {
+						FLUSH
+					}

-				if (!--width) break;
+				} else {
+					tc = 0xff;
+					tc_1 = 0xfe;
+
+					if (vc->vc_need_wrap || vc->vc_decim)
+						FLUSH
+					if (vc->vc_need_wrap) {
+						cr(vc);
+						lf(vc);
+					}
+
+					if (vc->vc_decim)
+						insert_char(vc, 1);
+					scr_writew(himask ?
+						     ((vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) +
(tc & 0xff) :
+						     (vc_attr << 8) + tc,
+						   (u16 *) vc->vc_pos);
+					scr_writew(c,
+						   (u16 *) vc->vc_pos + (vc->vc_screenbuf_size >> 1));
+					if (DO_UPDATE(vc) && draw_x < 0) {
+						draw_x = vc->vc_x;
+						draw_from = vc->vc_pos;
+					}
+					if (vc->vc_x == vc->vc_cols - 1) {
+						vc->vc_need_wrap = vc->vc_decawm;
+						draw_to = vc->vc_pos + 2;
+					} else {
+						vc->vc_x++;
+						draw_to = (vc->vc_pos += 2);
+					}
+
+					if (!--width) break;
+	
+					tc = conv_uni_to_pc(vc, ' '); /* A space is printed in the
second column */
+					if (tc < 0) tc = ' ';
+
+					notify_write(vc, c);
+
+					if (inverse) {
+						FLUSH
+					}
+
+
+					if (vc->vc_need_wrap || vc->vc_decim)
+						FLUSH
+					if (vc->vc_need_wrap) {
+						cr(vc);
+						lf(vc);
+					}
+
+					if (vc->vc_decim)
+						insert_char(vc, 1);
+					scr_writew(himask ?
+						     ((vc_attr << 8) & ~himask) + ((tc_1 & 0x100) ? himask : 0)
+ (tc_1 & 0xff) :
+						     (vc_attr << 8) + tc_1,
+						   (u16 *) vc->vc_pos);
+					scr_writew(c,
+						   (u16 *) vc->vc_pos + (vc->vc_screenbuf_size >> 1));
+					if (DO_UPDATE(vc) && draw_x < 0) {
+						draw_x = vc->vc_x;
+						draw_from = vc->vc_pos;
+					}
+					if (vc->vc_x == vc->vc_cols - 1) {
+						vc->vc_need_wrap = vc->vc_decawm;
+						draw_to = vc->vc_pos + 2;
+					} else {
+						vc->vc_x++;
+						draw_to = (vc->vc_pos += 2);
+					}
+
+					if (!--width) break;
+	
+					tc = conv_uni_to_pc(vc, ' '); /* A space is printed in the
second column */
+					if (tc < 0) tc = ' ';

-				tc = conv_uni_to_pc(vc, ' '); /* A space is printed in the second column */
-				if (tc < 0) tc = ' ';
-			}
-			notify_write(vc, c);
+					notify_write(vc, c);

-			if (inverse) {
-				FLUSH
+					if (inverse) {
+						FLUSH
+					}
+				}
 			}

 			if (rescan) {
@@ -2920,7 +3044,7 @@ static int __init con_init(void)
 		INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK);
 		tty_port_init(&vc->port);
 		visual_init(vc, currcons, 1);
-		vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT);
+		vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size * 2, GFP_NOWAIT);
 		vc_init(vc, vc->vc_rows, vc->vc_cols,
 			currcons || !vc->vc_sw->con_save_screen);
 	}
@@ -4142,9 +4266,15 @@ u16 screen_glyph(struct vc_data *vc, int offset)
 	u16 w = scr_readw(screenpos(vc, offset, 1));
 	u16 c = w & 0xff;

-	if (w & vc->vc_hi_font_mask)
-		c |= 0x100;
-	return c;
+	u16 c_utf8 = scr_readw(screenpos_utf8(vc, offset, 1));
+
+	if ( (c == 0xff || c == 0xfe) && c_utf8 != 0){
+		return c_utf8;
+	}else{
+		if (w & vc->vc_hi_font_mask)
+			c |= 0x100;
+		return c;
+	}
 }
 EXPORT_SYMBOL_GPL(screen_glyph);

diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
index 28b1a83..1d15a28 100644
--- a/drivers/video/console/bitblit.c
+++ b/drivers/video/console/bitblit.c
@@ -10,6 +10,7 @@
  *  more details.
  */

+#include <linux/font.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/string.h>
@@ -43,6 +44,21 @@ static void update_attr(u8 *dst, u8 *src, int attribute,
 	}
 }

+static inline u16 utf8_pos(struct vc_data *vc, const unsigned short *utf8)
+{
+	unsigned long p = (long)utf8;
+	if (p >= vc->vc_origin && p < vc->vc_scr_end) {
+		return scr_readw((unsigned short *)(p + vc->vc_screenbuf_size));
+	} else if (vc->vc_num == fg_console && fbcon_is_softback(utf8)){
+		return scr_readw((unsigned short *)(p + fbcon_softback_size));
+	} else {
+		u16 extra_c;
+		int c = *(int*)utf8;
+		extra_c = (c >> 16 ) & 0x0000ffff;
+		return extra_c;
+	}
+}
+
 static void bit_bmove(struct vc_data *vc, struct fb_info *info, int sy,
 		      int sx, int dy, int dx, int height, int width)
 {
@@ -74,6 +90,34 @@ static void bit_clear(struct vc_data *vc, struct
fb_info *info, int sy,
 	info->fbops->fb_fillrect(info, &region);
 }

+u8 * font_bits(struct vc_data *vc, const u16 *s,u32 cellsize,
+					u16 charmask)
+{
+	u32	utf8_c;
+
+	u8 *src = vc->vc_font.data + (scr_readw(s)&
+				  charmask)*cellsize;
+
+	utf8_c = utf8_pos(vc, s);
+
+	if( utf8_c <= vc->vc_font.charcount)
+	{
+		/*
+		 * decide left-half char or right-half char.
+		 * Since non-English chars may double weight
+		 */
+		switch (scr_readw(s) & charmask) {
+			case 0xff:
+				src = vc->vc_font.data + (utf8_c * cellsize *2 );
+				break;
+			case 0xfe:
+				src = vc->vc_font.data + (utf8_c * cellsize *2 + cellsize);
+				break;
+		}
+	}
+	return src;
+}
+
 static inline void bit_putcs_aligned(struct vc_data *vc, struct fb_info *info,
 				     const u16 *s, u32 attr, u32 cnt,
 				     u32 d_pitch, u32 s_pitch, u32 cellsize,
@@ -84,14 +128,12 @@ static inline void bit_putcs_aligned(struct
vc_data *vc, struct fb_info *info,
 	u8 *src;

 	while (cnt--) {
-		src = vc->vc_font.data + (scr_readw(s++)&
-					  charmask)*cellsize;
+		src = font_bits(vc,s++,cellsize,charmask);

 		if (attr) {
 			update_attr(buf, src, attr, vc);
 			src = buf;
 		}
-
 		if (likely(idx == 1))
 			__fb_pad_aligned_buffer(dst, d_pitch, src, idx,
 						image->height);
@@ -119,14 +161,11 @@ static inline void bit_putcs_unaligned(struct vc_data *vc,
 	u8 *src;

 	while (cnt--) {
-		src = vc->vc_font.data + (scr_readw(s++)&
-					  charmask)*cellsize;
-
+		src = font_bits(vc,s++,cellsize,charmask);
 		if (attr) {
 			update_attr(buf, src, attr, vc);
 			src = buf;
 		}
-
 		fb_pad_unaligned_buffer(dst, d_pitch, src, idx,
 					image->height, shift_high,
 					shift_low, mod);
@@ -246,6 +285,8 @@ static void bit_cursor(struct vc_data *vc, struct
fb_info *info, int mode,
 	int err = 1;
 	char *src;

+	int cellsize = DIV_ROUND_UP(vc->vc_font.width,8) * vc->vc_font.height;
+
 	cursor.set = 0;

 	if (softback_lines) {
@@ -259,7 +300,7 @@ static void bit_cursor(struct vc_data *vc, struct
fb_info *info, int mode,

  	c = scr_readw((u16 *) vc->vc_pos);
 	attribute = get_attribute(info, c);
-	src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
+	src = font_bits(vc,(u16*)vc->vc_pos,cellsize,charmask);

 	if (ops->cursor_state.image.data != src ||
 	    ops->cursor_reset) {
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 7ccc967..04c60f4 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -103,7 +103,8 @@ static int logo_lines;
    enums.  */
 static int logo_shown = FBCON_LOGO_CANSHOW;
 /* Software scrollback */
-static int fbcon_softback_size = 32768;
+/*I need to use it out side fbcon.c */
+int fbcon_softback_size = 32768;
 static unsigned long softback_buf, softback_curr;
 static unsigned long softback_in;
 static unsigned long softback_top, softback_end;
@@ -196,6 +197,14 @@ static void fbcon_start(void);
 static void fbcon_exit(void);
 static struct device *fbcon_device;

+int fbcon_is_softback(const unsigned short *str)
+{
+	unsigned long p = (long)str;
+	if(p >= softback_buf && p <softback_end)
+		return 1;
+	return 0;
+}
+
 #ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION
 static inline void fbcon_set_rotation(struct fb_info *info)
 {
@@ -965,7 +974,7 @@ static const char *fbcon_startup(void)
 			if (!softback_buf) {
 				softback_buf =
 				    (unsigned long)
-				    kmalloc(fbcon_softback_size,
+				    kmalloc(fbcon_softback_size * 2,
 					    GFP_KERNEL);
 				if (!softback_buf) {
 					fbcon_softback_size = 0;
@@ -995,7 +1004,8 @@ static const char *fbcon_startup(void)
 		vc->vc_font.width = font->width;
 		vc->vc_font.height = font->height;
 		vc->vc_font.data = (void *)(p->fontdata = font->data);
-		vc->vc_font.charcount = 256; /* FIXME  Need to support more fonts */
+		// read charcount from font_desc, yep, finally fixed
+		vc->vc_font.charcount = font->charcount;
 	}

 	cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
@@ -1066,8 +1076,8 @@ static void fbcon_init(struct vc_data *vc, int init)
 			vc->vc_font.width = font->width;
 			vc->vc_font.height = font->height;
 			vc->vc_font.data = (void *)(p->fontdata = font->data);
-			vc->vc_font.charcount = 256; /* FIXME  Need to
-							support more fonts */
+			// read charcount from font , finnaly fixed
+			vc->vc_font.charcount = font->charcount;
 		}
 	}

@@ -1268,10 +1278,7 @@ static void fbcon_putcs(struct vc_data *vc,
const unsigned short *s,

 static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos)
 {
-	unsigned short chr;
-
-	scr_writew(c, &chr);
-	fbcon_putcs(vc, &chr, 1, ypos, xpos);
+	fbcon_putcs(vc, (unsigned short *)&c, 1, ypos, xpos);
 }

 static void fbcon_clear_margins(struct vc_data *vc, int bottom_only)
@@ -1522,6 +1529,7 @@ static __inline__ void ypan_down_redraw(struct
vc_data *vc, int t, int count)
 static void fbcon_redraw_softback(struct vc_data *vc, struct display *p,
 				  long delta)
 {
+	u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
 	int count = vc->vc_rows;
 	unsigned short *d, *s;
 	unsigned long n;
@@ -1584,6 +1592,8 @@ static void fbcon_redraw_softback(struct vc_data
*vc, struct display *p,
 					start = s;
 				}
 			}
+			if( ((scr_readw(s) & charmask) == 0xff || (scr_readw(s) &
charmask) == 0xfe) && scr_readw(s + (vc->vc_screenbuf_size >> 1)) !=
0){
+			}else{
 			if (c == scr_readw(d)) {
 				if (s > start) {
 					fbcon_putcs(vc, start, s - start,
@@ -1595,6 +1605,7 @@ static void fbcon_redraw_softback(struct vc_data
*vc, struct display *p,
 					start++;
 				}
 			}
+			}
 			s++;
 			d++;
 		} while (s < le);
@@ -1677,6 +1688,7 @@ static void fbcon_redraw_blit(struct vc_data
*vc, struct fb_info *info,
 			}

 			scr_writew(c, d);
+			scr_writew(scr_readw(s + (vc->vc_screenbuf_size >> 1)), d +
(vc->vc_screenbuf_size >> 1));
 			console_conditional_schedule();
 			s++;
 			d++;
@@ -1699,6 +1711,7 @@ static void fbcon_redraw_blit(struct vc_data
*vc, struct fb_info *info,
 static void fbcon_redraw(struct vc_data *vc, struct display *p,
 			 int line, int count, int offset)
 {
+	u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
 	unsigned short *d = (unsigned short *)
 	    (vc->vc_origin + vc->vc_size_row * line);
 	unsigned short *s = d + offset;
@@ -1721,18 +1734,22 @@ static void fbcon_redraw(struct vc_data *vc,
struct display *p,
 					start = s;
 				}
 			}
-			if (c == scr_readw(d)) {
-				if (s > start) {
-					fbcon_putcs(vc, start, s - start,
-						     line, x);
-					x += s - start + 1;
-					start = s + 1;
-				} else {
-					x++;
-					start++;
+			if( ((scr_readw(s) & charmask) == 0xff || (scr_readw(s) &
charmask) == 0xfe) && scr_readw(s + (vc->vc_screenbuf_size >> 1)) !=
0){
+			}else{
+				if (c == scr_readw(d)) {
+					if (s > start) {
+						fbcon_putcs(vc, start, s - start,
+							     line, x);
+						x += s - start + 1;
+						start = s + 1;
+					} else {
+						x++;
+						start++;
+					}
 				}
 			}
 			scr_writew(c, d);
+			scr_writew(scr_readw(s + (vc->vc_screenbuf_size >> 1)), d +
(vc->vc_screenbuf_size >> 1));
 			console_conditional_schedule();
 			s++;
 			d++;
@@ -1762,6 +1779,7 @@ static inline void fbcon_softback_note(struct
vc_data *vc, int t,

 	while (count) {
 		scr_memcpyw((u16 *) softback_in, p, vc->vc_size_row);
+		scr_memcpyw((u16 *) softback_in + (fbcon_softback_size >> 1), p +
(vc->vc_screenbuf_size >> 1), vc->vc_size_row);
 		count--;
 		p = advance_row(p, 1);
 		softback_in += vc->vc_size_row;
@@ -2376,7 +2394,6 @@ static int fbcon_get_font(struct vc_data *vc,
struct console_font *font)

 	font->width = vc->vc_font.width;
 	font->height = vc->vc_font.height;
-	font->charcount = vc->vc_hi_font_mask ? 512 : 256;
 	if (!font->data)
 		return 0;

@@ -2672,6 +2689,19 @@ static u16 *fbcon_screen_pos(struct vc_data
*vc, int offset)
 	unsigned long p;
 	int line;
 	
+	if (offset < 0) {
+		offset = -offset - 1;
+		if (vc->vc_num != fg_console || !softback_lines)
+			return (u16 *)(vc->vc_origin + offset + (vc->vc_screenbuf_size));
+		line = offset / vc->vc_size_row;
+		if (line >= softback_lines)
+			return (u16 *) (vc->vc_origin + offset - softback_lines *
vc->vc_size_row + (vc->vc_screenbuf_size));
+		p = softback_curr + offset;
+		if (p >= softback_end)
+			p += softback_buf - softback_end;
+		return (u16 *) (p + (fbcon_softback_size));
+	}
+
 	if (vc->vc_num != fg_console || !softback_lines)
 		return (u16 *) (vc->vc_origin + offset);
 	line = offset / vc->vc_size_row;
@@ -2779,6 +2809,8 @@ static int fbcon_scrolldelta(struct vc_data *vc,
int lines)
 					q -= vc->vc_size_row;
 					scr_memcpyw((u16 *) q, (u16 *) p,
 						    vc->vc_size_row);
+					scr_memcpyw((u16 *) (q + (vc->vc_screenbuf_size >> 1)), (u16 *)
(p + (fbcon_softback_size >> 1)),
+						    vc->vc_size_row);
 				}
 				softback_in = softback_curr = p;
 				update_region(vc, vc->vc_origin,
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
index 6bd2e0c..b41cb0f 100644
--- a/drivers/video/console/fbcon.h
+++ b/drivers/video/console/fbcon.h
@@ -260,5 +260,8 @@ extern void fbcon_set_rotate(struct fbcon_ops *ops);
 #define fbcon_set_rotate(x) do {} while(0)
 #endif /* CONFIG_FRAMEBUFFER_CONSOLE_ROTATION */

+extern int fbcon_softback_size;
+extern int fbcon_is_softback(const unsigned short *str);
+
 #endif /* _VIDEO_FBCON_H */

diff --git a/drivers/video/console/fbcon_ccw.c
b/drivers/video/console/fbcon_ccw.c
index 41b32ae..44efb93 100644
--- a/drivers/video/console/fbcon_ccw.c
+++ b/drivers/video/console/fbcon_ccw.c
@@ -17,6 +17,9 @@
 #include <asm/types.h>
 #include "fbcon.h"
 #include "fbcon_rotate.h"
+#include "fonts_utf8.h"
+
+extern u16 utf8_pos(struct vc_data *vc, const unsigned short *utf8);

 /*
  * Rotation 270 degrees
@@ -105,13 +108,23 @@ static inline void ccw_putcs_aligned(struct
vc_data *vc, struct fb_info *info,
 	u32 idx = (vc->vc_font.height + 7) >> 3;
 	u8 *src;

-	while (cnt--) {
-		src = ops->fontbuffer + (scr_readw(s--) & charmask)*cellsize;

+	while (cnt--) {
+		if(((scr_readw(s) & charmask) == 0xff || (scr_readw(s) & charmask)
== 0xfe )){
+			char dst[16];
+			src = font_bits(vc,s,cellsize,charmask);
+			memset(dst, 0, 16);
+			rotate_ccw(src, dst, vc->vc_font.width,
+				  vc->vc_font.height);
+			src = dst;
+		}else{
+			src = ops->fontbuffer + (scr_readw(s) & charmask)*cellsize;
+		}
 		if (attr) {
 			ccw_update_attr(buf, src, attr, vc);
 			src = buf;
 		}
+		s--;

 		if (likely(idx == 1))
 			__fb_pad_aligned_buffer(dst, d_pitch, src, idx,
@@ -225,12 +238,14 @@ static void ccw_cursor(struct vc_data *vc,
struct fb_info *info, int mode,
 	struct fb_cursor cursor;
 	struct fbcon_ops *ops = info->fbcon_par;
 	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+	int c_extra;
 	int w = (vc->vc_font.height + 7) >> 3, c;
 	int y = real_y(ops->p, vc->vc_y);
 	int attribute, use_sw = (vc->vc_cursor_type & 0x10);
 	int err = 1, dx, dy;
 	char *src;
 	u32 vyres = GETVYRES(ops->p->scrollmode, info);
+	int cellsize = DIV_ROUND_UP(vc->vc_font.width,8) * vc->vc_font.height;

 	if (!ops->fontbuffer)
 		return;
@@ -246,9 +261,19 @@ static void ccw_cursor(struct vc_data *vc, struct
fb_info *info, int mode,
 			y += softback_lines;
 	}

- 	c = scr_readw((u16 *) vc->vc_pos);
+	c = scr_readw((u16 *) vc->vc_pos);
 	attribute = get_attribute(info, c);
-	src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
+
+	if(((c&charmask) == 0xff || (c & charmask) == 0xfe) && c_extra != 0){
+		char dst[16];
+		src = font_bits(vc,s,cellsize,charmask);
+		memset(dst, 0, 16);
+		rotate_ccw(src, dst, vc->vc_font.width,
+			  vc->vc_font.height);
+		src = dst;
+	}else{
+		src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
+	}

 	if (ops->cursor_state.image.data != src ||
 	    ops->cursor_reset) {
diff --git a/drivers/video/console/fbcon_cw.c b/drivers/video/console/fbcon_cw.c
index 6a73782..c15138e 100644
--- a/drivers/video/console/fbcon_cw.c
+++ b/drivers/video/console/fbcon_cw.c
@@ -18,6 +18,8 @@
 #include "fbcon.h"
 #include "fbcon_rotate.h"

+extern u8 * font_bits(struct vc_data *vc, const u16 *s,u32 cellsize,
+		u16 charmask);
 /*
  * Rotation 90 degrees
  */
@@ -90,14 +92,22 @@ static inline void cw_putcs_aligned(struct vc_data
*vc, struct fb_info *info,
 	u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
 	u32 idx = (vc->vc_font.height + 7) >> 3;
 	u8 *src;
-
 	while (cnt--) {
-		src = ops->fontbuffer + (scr_readw(s++) & charmask)*cellsize;
-
+		if(((scr_readw(s) & charmask) == 0xff || (scr_readw(s) & charmask)
== 0xfe ) &&  utf8_c != 0){
+			char dst[16];
+			src = font_bits(vc,s,cellsize,charmask);
+			memset(dst, 0, 16);
+			rotate_cw(src, dst, vc->vc_font.width,
+				  vc->vc_font.height);
+			src = dst;
+		}else{
+			src = ops->fontbuffer + (scr_readw(s) & charmask)*cellsize;
+		}
 		if (attr) {
 			cw_update_attr(buf, src, attr, vc);
 			src = buf;
 		}
+		s++;

 		if (likely(idx == 1))
 			__fb_pad_aligned_buffer(dst, d_pitch, src, idx,
@@ -209,12 +219,14 @@ static void cw_cursor(struct vc_data *vc, struct
fb_info *info, int mode,
 	struct fb_cursor cursor;
 	struct fbcon_ops *ops = info->fbcon_par;
 	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+	int c_extra;
 	int w = (vc->vc_font.height + 7) >> 3, c;
 	int y = real_y(ops->p, vc->vc_y);
 	int attribute, use_sw = (vc->vc_cursor_type & 0x10);
 	int err = 1, dx, dy;
 	char *src;
 	u32 vxres = GETVXRES(ops->p->scrollmode, info);
+	int cellsize = DIV_ROUND_UP(vc->vc_font.width,8) * vc->vc_font.height;

 	if (!ops->fontbuffer)
 		return;
@@ -232,7 +244,16 @@ static void cw_cursor(struct vc_data *vc, struct
fb_info *info, int mode,

  	c = scr_readw((u16 *) vc->vc_pos);
 	attribute = get_attribute(info, c);
-	src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
+	if(((c&charmask) == 0xff || (c & charmask) == 0xfe)){
+		char dst[16];
+		src = font_bits(vc,s,cellsize,charmask);
+		memset(dst, 0, 16);
+		rotate_cw(src, dst, vc->vc_font.width,
+			  vc->vc_font.height);
+		src = dst;
+	}else{
+		src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
+	}

 	if (ops->cursor_state.image.data != src ||
 	    ops->cursor_reset) {
diff --git a/drivers/video/console/fbcon_ud.c b/drivers/video/console/fbcon_ud.c
index ff0872c..ed2022b 100644
--- a/drivers/video/console/fbcon_ud.c
+++ b/drivers/video/console/fbcon_ud.c
@@ -18,6 +18,8 @@
 #include "fbcon.h"
 #include "fbcon_rotate.h"

+extern u8 * font_bits(struct vc_data *vc, const u16 *s,u32 cellsize,
+		u16 charmask);
 /*
  * Rotation 180 degrees
  */
@@ -93,12 +95,22 @@ static inline void ud_putcs_aligned(struct vc_data
*vc, struct fb_info *info,
 	u8 *src;

 	while (cnt--) {
-		src = ops->fontbuffer + (scr_readw(s--) & charmask)*cellsize;

+		if(((scr_readw(s) & charmask) == 0xff || (scr_readw(s) & charmask)
== 0xfe ) ){
+			char dst[16];
+			src = font_bits(vc,s,cellsize,charmask);
+			memset(dst, 0, 16);
+			rotate_ud(src, dst, vc->vc_font.width,
+				  vc->vc_font.height);
+			src = dst;
+		}else{
+			src = ops->fontbuffer + (scr_readw(s) & charmask)*cellsize;
+		}
 		if (attr) {
 			ud_update_attr(buf, src, attr, vc);
 			src = buf;
 		}
+		s--;

 		if (likely(idx == 1))
 			__fb_pad_aligned_buffer(dst, d_pitch, src, idx,
@@ -128,12 +140,21 @@ static inline void ud_putcs_unaligned(struct vc_data *vc,
 	u8 *src;

 	while (cnt--) {
-		src = ops->fontbuffer + (scr_readw(s--) & charmask)*cellsize;
-
+		if(((scr_readw(s) & charmask) == 0xff || (scr_readw(s) & charmask)
== 0xfe )){
+			char dst[16];
+			src = font_bits(vc,s,cellsize,charmask);
+			memset(dst, 0, 16);
+			rotate_ud(src, dst, vc->vc_font.width,
+				  vc->vc_font.height);
+			src = dst;
+		}else{
+			src = ops->fontbuffer + (scr_readw(s) & charmask)*cellsize;
+		}
 		if (attr) {
 			ud_update_attr(buf, src, attr, vc);
 			src = buf;
 		}
+		s--;

 		fb_pad_unaligned_buffer(dst, d_pitch, src, idx,
 					image->height, shift_high,
@@ -255,6 +276,7 @@ static void ud_cursor(struct vc_data *vc, struct
fb_info *info, int mode,
 	struct fb_cursor cursor;
 	struct fbcon_ops *ops = info->fbcon_par;
 	unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+	int c_extra;
 	int w = (vc->vc_font.width + 7) >> 3, c;
 	int y = real_y(ops->p, vc->vc_y);
 	int attribute, use_sw = (vc->vc_cursor_type & 0x10);
@@ -262,6 +284,7 @@ static void ud_cursor(struct vc_data *vc, struct
fb_info *info, int mode,
 	char *src;
 	u32 vyres = GETVYRES(ops->p->scrollmode, info);
 	u32 vxres = GETVXRES(ops->p->scrollmode, info);
+	int cellsize = DIV_ROUND_UP(vc->vc_font.width,8) * vc->vc_font.height;

 	if (!ops->fontbuffer)
 		return;
@@ -279,7 +302,18 @@ static void ud_cursor(struct vc_data *vc, struct
fb_info *info, int mode,

  	c = scr_readw((u16 *) vc->vc_pos);
 	attribute = get_attribute(info, c);
-	src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.height));
+	if(((c&charmask) == 0xff || (c & charmask) == 0xfe) ){
+		char dst[16];
+
+		src = font_bits(vc,s,cellsize,charmask);
+
+		memset(dst, 0, 16);
+		rotate_ud(src, dst, vc->vc_font.width,
+			  vc->vc_font.height);
+		src = dst;
+	}else{
+		src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.height));
+	}

 	if (ops->cursor_state.image.data != src ||
 	    ops->cursor_reset) {
diff --git a/drivers/video/console/font_10x18.c
b/drivers/video/console/font_10x18.c
index 6be72bb..8bd2857 100644
--- a/drivers/video/console/font_10x18.c
+++ b/drivers/video/console/font_10x18.c
@@ -5143,4 +5143,5 @@ const struct font_desc font_10x18 = {
 #else
 	.pref	= -1,
 #endif
+	.charcount = 255,
 };
diff --git a/drivers/video/console/font_6x11.c
b/drivers/video/console/font_6x11.c
index 46e86e6..0c73fc9 100644
--- a/drivers/video/console/font_6x11.c
+++ b/drivers/video/console/font_6x11.c
@@ -3349,4 +3349,5 @@ const struct font_desc font_vga_6x11 = {
 	.data	= fontdata_6x11,
 	/* Try avoiding this font if possible unless on MAC */
 	.pref	= -2000,
+	.charcount = 255,
 };
diff --git a/drivers/video/console/font_7x14.c
b/drivers/video/console/font_7x14.c
index 3b7dbf9..2b7f3f0 100644
--- a/drivers/video/console/font_7x14.c
+++ b/drivers/video/console/font_7x14.c
@@ -4115,4 +4115,5 @@ const struct font_desc font_7x14 = {
 	.height	= 14,
 	.data	= fontdata_7x14,
 	.pref	= 0,
+	.charcount = 255,
 };
diff --git a/drivers/video/console/font_8x16.c
b/drivers/video/console/font_8x16.c
index 00a0c67..2826dd2 100644
--- a/drivers/video/console/font_8x16.c
+++ b/drivers/video/console/font_8x16.c
@@ -4629,5 +4629,6 @@ const struct font_desc font_vga_8x16 = {
 	.height	= 16,
 	.data	= fontdata_8x16,
 	.pref	= 0,
+	.charcount = 255,
 };
 EXPORT_SYMBOL(font_vga_8x16);
diff --git a/drivers/video/console/font_8x8.c b/drivers/video/console/font_8x8.c
index 9f56efe..3d924f3 100644
--- a/drivers/video/console/font_8x8.c
+++ b/drivers/video/console/font_8x8.c
@@ -2580,4 +2580,5 @@ const struct font_desc font_vga_8x8 = {
 	.height	= 8,
 	.data	= fontdata_8x8,
 	.pref	= 0,
+	.charcount = 255,
 };
diff --git a/drivers/video/console/font_acorn_8x8.c
b/drivers/video/console/font_acorn_8x8.c
index 639e31a..8c5a0f6 100644
--- a/drivers/video/console/font_acorn_8x8.c
+++ b/drivers/video/console/font_acorn_8x8.c
@@ -272,4 +272,5 @@ const struct font_desc font_acorn_8x8 = {
 #else
 	.pref	= 0,
 #endif
+	.charcount = 255,
 };
diff --git a/drivers/video/console/font_mini_4x6.c
b/drivers/video/console/font_mini_4x6.c
index a19a7f3..c6245a6 100644
--- a/drivers/video/console/font_mini_4x6.c
+++ b/drivers/video/console/font_mini_4x6.c
@@ -2154,5 +2154,6 @@ const struct font_desc font_mini_4x6 = {
 	.height	= 6,
 	.data	= fontdata_mini_4x6,
 	.pref	= 3,
+	.charcount = 255,
 };

diff --git a/drivers/video/console/font_pearl_8x8.c
b/drivers/video/console/font_pearl_8x8.c
index dc6ad53..a3ae722 100644
--- a/drivers/video/console/font_pearl_8x8.c
+++ b/drivers/video/console/font_pearl_8x8.c
@@ -2584,4 +2584,5 @@ const struct font_desc font_pearl_8x8 = {
 	.height	= 8,
 	.data	= fontdata_pearl8x8,
 	.pref	= 2,
+	.charcount = 255,
 };
diff --git a/drivers/video/console/font_sun12x22.c
b/drivers/video/console/font_sun12x22.c
index d364385..e61a98b 100644
--- a/drivers/video/console/font_sun12x22.c
+++ b/drivers/video/console/font_sun12x22.c
@@ -6162,4 +6162,5 @@ const struct font_desc font_sun_12x22 = {
 #else
 	.pref	= -1,
 #endif
+	.charcount = 255,
 };
diff --git a/drivers/video/console/font_sun8x16.c
b/drivers/video/console/font_sun8x16.c
index 5abf290..2151bfb 100644
--- a/drivers/video/console/font_sun8x16.c
+++ b/drivers/video/console/font_sun8x16.c
@@ -272,4 +272,5 @@ const struct font_desc font_sun_8x16 = {
 #else
 	.pref	= -1,
 #endif
+	.charcount = 255,
 };
diff --git a/include/linux/font.h b/include/linux/font.h
index 40a24ab..43676f0 100644
--- a/include/linux/font.h
+++ b/include/linux/font.h
@@ -19,6 +19,7 @@ struct font_desc {
     int width, height;
     const void *data;
     int pref;
+    int charcount;
 };

 #define VGA8x8_IDX	0
-- 
1.7.3.1


关于邮件列表 Chinese 的更多信息